2011-01-23 22 views
7

Więc insteed pisania:Co jest nie tak z ?? operator używany tak:

if (obj.Collection == null) 
    obj.Collection = new Collection(); 
obj.Collection.Add(something); 

myślałem o piśmie:

obj.Collection = obj.Collection ?? new Collection; 
obj.Collection.Add(something); 

To niby czuje się źle, zwłaszcza tę część „obj.Collection = obj.Collection .. . "

Co wy myślicie?

Chodzi,

+4

Dlaczego czuje się źle? – alexn

+0

Wydaje mi się nieszkodliwy – Vadim

+4

Na czym polega problem? Czy masz problem z 'x = x + 1;'? –

Odpowiedz

15

Gdybym miał wybrać między tymi dwoma blokami kodu, użyłbym tego pierwszego. Jest bardziej czytelny i ma wspólny wzorzec. ?? jest przydatny w scenariuszach, w których należy ustawić wartość domyślną (np. DateTime date = nullableDateTimeInstance ?? defaultDate;).

Ale, szczerze mówiąc, starałbym się nie skończyć w sytuacji, w której chcę dodać do kolekcji i możliwe, że kolekcja jest zerowa. Zamiast tego upewniam się, że kolekcja jest inicjowana w konstruktorze lub w jakimkolwiek innym przypadku.

+1

Lub nawet dokonać inicjalizacji w pobierającym własności! –

+0

Masz rację, ale jeśli Collection jest wirtualnym członkiem klasy (powiedzmy nhibernate entity class). Wtedy otrzymasz ostrzeżenie "Wirtualne wywołanie członka w konstruktorze". Wolę powyższe niż to ostrzeżenie. – Calin

+0

@Calin: Podaj bardzo prosty blok kodu, który odtwarza ostrzeżenie, które opisujesz, ponieważ uważam, że zrobione poprawnie, tak nie powinno być. – jason

0

kodu emitują niepotrzebne przypisania (na obj.Collection do siebie), jeżeli obj.Collection nie jest pusty, ale inne od tego, które jest równoważne z oryginałem.

Wygląda dla mnie dobrze, pod warunkiem, że nie użyjesz go w krytycznych sekcjach. W każdym razie jest możliwe, że kompilator może zoptymalizować zadanie, ale nie wiem, czy to możliwe, czy nie.

Może to po prostu źle, ponieważ oryginalny kod jest tak powszechny i ​​prosty, że źle się go zmienia.

3

Czy chodziło Ci o:

if (obj.Collection == null) 
    { 
     obj.Collection = new Collection(); 
    } 
obj.Collection.Add(something); 

Jeśli tak, można przerobić go jako

(obj.Collection = (obj.Collection ?? new Collection())).Add(something); 
+0

Błąd kompilatora, spróbuj ponownie. – leppie

+0

'(obj.Collection ?? (obj.Collection = new Collection())). Dodaj (coś);' będzie działać jednak. – leppie

+0

Tak, zdałem sobie z tego sprawę wkrótce po opublikowaniu odpowiedzi i poprawiłem ją. – tenor

0

powiedziałbym, że zależy również od tego, co seter nieruchomości Collection robi. Rozważ to:

public Collection Collection 
{ 
    get { return _collection; } 
    set 
    { 
     _collection = value; 
     Thread.Sleep(1000); // or some expensive real work 
    } 
} 

w tym przypadku cesji obj.Collection = obj.Collection ?? new Collection() byłoby bardzo kosztowne.

Jednakże, jeśli trzeba utworzyć kolekcję „na żądanie”, to powszechnie używa podobny wzór w getter własności, podobnie jak to:

public Collection Collection 
{ 
    get { return _collection ?? (_collection = new Collection()); } 
}