Recentemente il mio collega mi ha mostrato un blocco di codice che non funzionava correttamente:C operatore # nullo coalescenza ritorno nullo
public class SomeClass
{
private IList<Category> _categories;
public void SetCategories()
{
_categories = GetCategories() ?? new List<Category>();
DoSomethingElse();
}
public IList<Category> GetCategories()
{
return RetrieveCategories().Select(Something).ToList();
}
}
(Sono consapevole del fatto che l'operatore è superfluo in quanto il ToList LINQ restituirà sempre un lista, ma è così che è stato impostato il codice).
Il problema era che _categories era null. Nel debugger, impostando un punto di interruzione su _categories = GetCategories() ?? new List<Category>()
, quindi passando a DoSomethingElse(), le categorie _ sarebbero ancora nulle.
L'impostazione diretta di _categories su GetCategories() ha funzionato correttamente. Dividere il ?? in una dichiarazione completa se funzionava bene. L'operatore null coalescente no.
È un'applicazione ASP.NET, quindi un thread diverso potrebbe interferire, ma era sulla sua macchina, con solo lui connesso in un browser. _cateogories non è statico o nulla.
Quello che mi chiedo è, come è possibile che ciò accada?
Edit:
solo per aggiungere alla bizzarria, _categories
è mai messo da nessuna parte, oltre che la funzione (a parte l'inizializzazione della classe).
il codice esatto, è in questo modo:
public class CategoryListControl
{
private ICategoryRepository _repo;
private IList<Category> _categories;
public override string Render(/* args */)
{
_repo = ServiceLocator.Get<ICategoryRepository>();
Category category = _repo.FindByUrl(url);
_categories = _repo.GetChildren(category) ?? new List<Category>();
Render(/* Some other rendering stuff */);
}
}
public class CategoryRepository : ICategoryRepository
{
private static IList<Category> _categories;
public IList<Category> GetChildren(Category parent)
{
return _categories.Where(c => c.Parent == parent).ToList<Category>();
}
}
Anche lo GetChildren magicamente restituito un valore nullo, CategoryListControl._categories ancora non dovrebbero mai, mai essere nullo. GetChildren non dovrebbe mai restituire mai null a causa di IEnumerable.ToList().
Edit 2:
Provando codice di @ smartcaveman, ho scoperto questo:
Category category = _repo.FindByUrl(url);
_categories = _repo.GetChildren(category) ?? new List<Category>();
_skins = skin; // When the debugger is here, _categories is null
Renderer.Render(output, _skins.Content, WriteContent); // When the debugger is here, _categories is fine.
Così, quando si prova if(_categories == null) throw new Exception()
, _categories è stato nullo sulla if, quindi scavalcando l'eccezione era non gettato.
Quindi, sembra che questo sia un bug di debugger.
È perché si sta creando un'istanza nell'istruzione? Forse bene, ma non l'ho mai usato prima. –
Potresti controllare di nuovo? Sto pensando "errore di debug". –
La parte affascinante qui è che 'GetCategories()' non è in grado di restituire 'null' in ogni caso. L'operatore coalescente è comunque inutile. –