2012-10-01 17 views
17

Mam strukturę, która (dla celów tego pytania) w znacznym stopniu naśladuje typ zbudowany w Point.Jak mogę sprawdzić, czy instancja została utworzona?

Muszę sprawdzić, czy został utworzony przed jego użyciem. Kiedy było Point, mogę to zrobić:

if (this.p == null) 

Ale teraz generuje następujący błąd:

Operator '==' cannot be applied to operands of type 'ProportionPoint' and '<null>'

Jak mogę porównać moją struct przed zerową? Czy istnieje inny sposób sprawdzenia wystąpienia?

+1

Dlaczego używasz struct przeciwko klasie? –

Odpowiedz

25

A struct jest typem wartości - nigdy nie jest pusta.

Można sprawdzić przed default(ProportionPoint), która jest domyślną wartością struktury (np. Zerem). Jednak dla punktu może być tak, że wartość domyślna - pochodzenie - jest również wartością "prawidłową".

Zamiast tego można użyć numeru Nullable<ProportionPoint>.

+0

Dzięki. Jesteś na miejscu o origin = wartość domyślna. Mógł użyć nullable, ale zdałem sobie sprawę, że zachowanie, które chcę, pasuje do klasy lepiej niż struct. –

+2

A to, a zwłaszcza brak, jest powodem, dla którego alarmująca liczba obiektów NHS była kiedyś "zlokalizowana" na południe od Ghany i na zachód od Gabonu. – CJPN

2

A struktura nie może być pusta. Jest to typ wartości typu, a nie typu referencyjnego. Musisz sprawdzić przeciwko właściwościom z wartościami domyślnymi. Coś jak:

if(p.X == 0 && p.Y == 0) 
2

Struktura nigdy nie może być pusta, więc nie można jej porównać do wartości zerowej. I struktura jest zawsze inicjowana - jeśli nie przez ciebie, to przez kompilator z wartościami domyślnymi.

7

Struktury są typami wartości i nigdy nie mogą być puste w przeciwieństwie do typów referencyjnych. Można sprawdzić wartość domyślną:

if (this.p == default(ProportionPoint)) 
+8

Należy zauważyć, że zaznaczenie wartości domyślnej nie pozwoli na rozróżnienie między wartością "niezainicjalizowaną" a wartością "prawidłowo zainicjalizowaną z wartościami domyślnymi" (np. (0, 0)). –

+9

@DarinDimitrov Nie działa dla mnie. Operatora "==" nie można zastosować do argumentów typu "Vhdx.RegionTableEntry" i "Vhdx.RegionTableEntry". –

+1

Nie działa. Musisz użyć operatora 'Equals', a nie' === – toddmo

-1

Zmienne struktury nie mogą być puste, jedną z opcji byłoby zadeklarowanie go jako zerowalnego.

1

Za pomocą pustych:

ProportionPoint? p1 = null; 
if (p1 == null) ... 

lub

if (!p1.HasValue) ... 
1

przeciwieństwie zmiennej lub wartość typu urządzenia, które jest odniesienia wartość zero lub jedno wystąpienie tego rodzaju stosuje się Zmienna strukturalna lub wartość to instancja struct. Jeśli ma się blok kodu rozpoczynający się od {Point myPoint; ...} i nic w bloku nie zamyka się przed MyPoint (zamknięcie występuje, gdy w bloku znajduje się yield return lub gdy metoda lambda lub anonimowa używa zmiennej z otaczającego bloku), wystąpienie Point pojawi się w pewnym momencie, zanim wykonanie zostanie wprowadzone do bloku i może przestać istnieć w dowolnym momencie po zakończeniu wykonywania bloku. W każdym kontekście, w którym można użyć zmiennej typu struct, struktura istnieje.

Powodem, dla którego wszystkie typy struktur są uważane za mające domyślny konstruktor typu "do niczego", jest to, że typy struktur występują niejawnie. Gdy wykonujemy instrukcję taką jak Point[] myPoints = new Point[100];, tworzy ona wypełnioną zero tablicę struktur 100Point; w trakcie tego procesu natychmiast powstają instancje punktów wypełnionych zerami.W C++, jeśli typ ma konstruktor, utworzenie tablicy tego typu wywoła konstruktor na każdym elemencie tablicy w sekwencji, zanim jakikolwiek kod zostanie mu przyznany dostęp do tablicy w pewnym momencie. Jeśli podczas konstruowania dowolnego elementu zostanie zgłoszony wyjątek, wygenerowany przez kompilator kod uruchomi deterministyczny destruktor na każdym elemencie, który został pomyślnie utworzony przed wyparowaniem samej tablicy. Chociaż jest to bardzo potężna funkcja, włączenie jej do .net znacznie skomplikowałoby strukturę.

3

ponieważ p jest strukturą, nigdy nie jest pusta, więc powinieneś porównać ją z jej domyślną wartością. Aby sprawdzić równoważność między wartością a wartością dafault. Jeśli używasz == dostaniesz

cannot be applied to operands of type 'ProportionPoint' and 'ProportionPoint' error 

ponieważ kodowanym nie dostać implementację == domyślnie. więc trzeba przeciążać == i = operatorów w swojej struktury, takie jak ten:

public static bool operator ==(firstOperand op1, secondOperand2 op2) 
{ 
    return op1.Equals(op2); 
} 

public static bool operator !=(firstOperand op1, secondOperand2 op2) 
{ 
    return !op1.Equals(op2); 
} 

, a następnie:

if (this.p == default(ProportionPoint)) 

Inną opcją jest użycie Równa bezpośrednio:

f (this.p.Equals.default(ProportionPoint)) 
-1

Zrobiłem metodę rozszerzenia, która działa tylko z wzorami:

public static bool IsNull<T>(this T source) where T:struct 
{ 
    return source.Equals(default(T)); 
} 

konwencji wywołania:

if(myStruct.IsNull()) 
    DoSomething(); 

Rozumiem, że to naprawdę nie jest sprawdzenie, czy to null. Gdybym jednak nadał mu bardziej precyzyjną nazwę, np. IsEmpty lub IsDefault, w ciągu sześciu miesięcy zapomniałbym, że jest tam i po zobaczeniu listy dostępnych metod, a nie jej wyboru. Technicznie nie jest to kontrola zerowa; ale koncepcyjnie tak jest.

-1

elemencie nie może być null, ale obejście sprawdzania struct przed jego domyślnie może dać fałszywie ujemne, jeśli rzeczywiście chcemy przechowywać wartości odpowiadające wartości domyślnych w niej w dowolnym momencie.

(Na przykład struktura o wartości (0,0,0) może być nietknięte domyślny, lub może to być przechowywanie punkt początkowy w przestrzeni 3D).

Innym rozwiązaniem, które pozwala uniknąć tego fałszywego negatywnego problemu byłoby po prostu dodaj inna właściwość struktury - np bool lub int - do śledzenia, czy dane zostały w nim zapisane. Następnie każdy konstruktor, który inicjuje strukturę z faktycznym zestawem danych, ustawia tę wartość na true/1. W domyślnej strukturze wartość ta nadal będzie wynosić false/0, więc sprawdzanie przed default(MyStruct) nigdy nie powinno dać fałszywego negatywu, nawet jeśli wszystkie pozostałe dane w nim przechowywane są zgodne z wartościami domyślnymi.

public Struct MyStruct { 
    public float x { get; private set; } 
    public bool initialized { get; private set; } 

    public MyStruct(float _x){ 
     x=_x; 
     initialized = true; 
    } 
} 
Powiązane problemy