2012-06-03 14 views
5

Próbuję zrozumieć jedną rzecz w tym kodzie:W jaki sposób CLR może ominąć błąd rzucania podczas przypisywania wartości pustej do struct?

Nullable<Int32> x = 5; 
Nullable<Int32> y = null; 
Console.WriteLine("x: HasValue={0}, Value={1}", x.HasValue, x.Value); 
Console.WriteLine("y: HasValue={0}, Value={1}", y.HasValue, y.GetValueOrDefault()); 

i wyjście to:

x: HasValue=True, Value=5 
y: HasValue=False, Value=0 

A rzeczą, że nie rozumiem, kiedy przechodzą null do y, wierzę w to wywołuje public static implicit operator Nullable<T>(T value), ale definicja tej metody inicjuje nową strukturę przekazującą value, która jest przypisana null, jednak metoda konstruktora nie sprawdza, czy jest ona równa zeru, czy nie, aby mogła przypisać default(T) do value.

Jak to się stało, że możemy przypisać tutaj null do struct i działa dobrze?

Czy możecie, chłopaki, czego tu brakuje? Nie rozumiem, jak to było po prostu ominęło null i zwrócono wartość domyślną.

kod Nullable wewnętrzna definicja:

http://codepaste.net/gtce6d

+0

jakiś powód nie używasz wbudowanego 'Nullable ' struct? –

+0

Po prostu uczę się wewnętrznej struktury typów zerowalnych – Tarik

+0

Jako sidenote: Twoja implementacja "równa się" jest zepsuty.Jeśli obie strony są niestandardowe zerowalne i oba są custom-null, zwróci false, ale powinno zwrócić true. | Nie powinno też się kompilować, ponieważ nie możesz mieć inicjalizatorów na polach instancji dla struktur. – CodesInChaos

Odpowiedz

6

uwierzyć, że nazywa public static operatora niejawna pustych (T wartość)

Nie nie, ponieważ T jest w tym przypadku Int32, a null nie jest Int32. Po prostu pozostawia zmienną domyślną y, co oznacza, że ​​dla struktury wszystkie bajty mają wartość 0. W rezultacie powstaje struktura, która ma HasValue, która zwraca false.

Nie można naprawdę przekazać null do struct, ale kompilator C# konwertuje to dla ciebie do domyślnej initalizacji.

+0

Co sprawia, że ​​ta struktura 'Nullable' i' Int32' nie jest? Jak to możliwe, że możesz przydzielić 'null', który nie wyrzuca błędu, a mimo to' Int32' ma? Jest tak dlatego, że ma "niejawne" przeciążanie? – Tarik

+0

I tak ustawiłem struct a null i wystąpił błąd: http://ideone.com/NIbfn – Tarik

+2

To, co czyni go nullable, jest zdefiniowane jako nullable . Struktura Nullable ma trochę magii kompilatora, aby ułatwić jej użycie. – TomTom

1

Domyślnym jest przypisana w konstruktorze zwanego przez new Nullable<T>(value); (linia 40)

+0

Ale dlaczego możemy przekazać wartość zerową do struktury? – Tarik

1

Domyślam się, że przypisanie null do wartości pustej wywołuje domyślny konstruktor. Jest to jedyny możliwy sposób, aby hasValue pozostało false.

+0

Czy nie mogą mieć niektórych instrukcji "if", aby sprawdzić, czy powinny zmienić właściwość HasValue? – SimpleVar

+0

@YoryeNathan może mogli, ale nie ma żadnych. faktycznie, chociaż nie mówi "tylko do odczytu" na polach, struktura jest niezmienna. hasValue i value są ustawione tylko w konstruktorze; więc tak, chociaż nie jest to pokazane w kodzie, domyślny konstruktor jest jedynym sposobem uzyskania wartości 'null'. –

+0

Ale 'struct' nie może mieć konstruktora bez parametrów. Jak to się nazywa? http://stackoverflow.com/questions/575901/why-struct-can-not-have-parameterless-constructor – Tarik

1

A Nullable<T> jest po prostu strukturą, która ma boolowskie pole wskazujące, czy ma wartość, oraz pole, które (jeśli pierwsze pole jest prawdziwe) wskazuje, jaka jest ta wartość. Niemożliwe jest ustawienie dowolnej struktury na null, a Nullable<T> nie jest wyjątkiem. Zamiast tego kompilator tłumaczy żądanie, aby ustawić Nullable<T> na null jako żądanie, aby ustawić wartość pola "ma wartość" (odzwierciedloną w właściwości HasValue) na wartość false i ustawić pole "wartość rzeczywista" (odzwierciedlone w właściwości Value) na wartość domyślną dla jego typ.

Osobiście uważam, udając, że Nullable<T> gdzie HasValue jest fałszywa jest null jest bardziej kłopotliwe niż pomocne, ale nie jestem Microsoft.Myślę, że to mógł być bardziej pomocny dla każdego rodzaju Nullable<T> mieć właściwości statycznej Nullable<T>.Null (co byłoby równoważne default(Nullable<T>), ale zachowanie Nullable<T> jest dostatecznie ugruntowane Wątpię, czy kiedykolwiek zmienić.

Powiązane problemy