2015-05-17 14 views
5

Mam ten kod, który pobiera wartość z klasy Test, a następnie konwertuje ją na typ. Drukuje poprawnie jako "Int32", ale kiedy testuję równość z inną zmienną o tej samej wartości, wypisuje "false". Podejrzewam, że tak jest, ponieważ testuje równanie odniesienia i że dwie zmienne są naprawdę obiektami. Czy istnieje sposób ich porównania, pamiętając, że nie będę znać typu wartości zwracanej do czasu wykonania (może to być ciąg, zmienna, inna klasa itp.)?Jak mogę porównać typy wartości nabyte z "GetValue" Reflection?

class Test{public int y;} 

static void Main() 
{ 
    var test1 = new Test{y=1}; 
    var test2 = new Test{y=1}; 
    var fields = test1.GetType().GetFields(); 
    var test1Value = fields[0].GetValue(test1); 
    var test2Value = fields[0].GetValue(test2); 
    var test1Converted = Convert.ChangeType(test1Value, test1Value.GetType()); 
    var test2Converted = Convert.ChangeType(test2Value, test2Value.GetType()); 
    Console.WriteLine(test1Converted); // prints Int32 
    Console.WriteLine(test1Converted == test2Converted); // prints false 
} 

Odpowiedz

3

Połączenia z numerem Convert są niepotrzebne. Wartości zwrócone przez GetValue są już int s. Po prostu ich rzucanie daje prawidłowy wynik.

private class Test 
{ 
    public int y; 
} 

private static void Main() 
{ 
    Test test1 = new Test { y = 1 }; 
    Test test2 = new Test { y = 1 }; 
    FieldInfo[] fields = test1.GetType().GetFields(); 
    int test1Value = (int)fields[0].GetValue(test1); 
    int test2Value = (int)fields[0].GetValue(test2); 
    Console.WriteLine(test1Value); // prints Int32 
    Console.WriteLine(test1Value == test2Value); // prints true 
} 

Powodem, że wartości un-lanego nie jest to, że Convert.ChangeType nadal zwraca object, który boxes INTów, więc rzeczywiście dostać równości odniesienia.

Innym sposobem, aby uzyskać prawidłową wartość jest wywołanie metody Equals, które zostaną prawidłowo kierowane do Int32.Equals i drukować true:

Console.WriteLine(test1Converted.Equals(test2Converted)); // prints true 

pamiętać, że w tym przypadku Convert.ChangeType nadal nie jest to konieczne.

+1

Equals zawiedzie na odniesienie type, tutaj jest to udane dla typu wartość/liczba całkowita, ponieważ porównuje wartość, to wymaga jawnego przesłonięcia metody Equals. –

+1

@MinalBamboj Czy możesz podać konkretny przykład, w którym typ odniesienia zakończyłby się niepowodzeniem? Wszystkie typy referencyjne * już * domyślnie odwołują się do równości i nie będą zapakowane w 'GetValue'. –

+0

Zgodnie z sugestią, Odniesienie równe odnosi się do równości odniesienia, dla domyślnej metody Równania, więc nie jest konieczne, aby dwie pobrane zmienne referencyjne zmienne poprzez odbicie wskazywałyby na to samo odniesienie, wymagałoby to jawnego przesłonięcia metody Równań w celu porównania wartości wewnętrznej dla bieżącej odpowiedzi –

1

Obiekt powrotu Convert.ChangeType(). Cast zwrócony obiekt do Int32:

var test1Converted = (Int32)Convert.ChangeType(test1Value, test1Value.GetType()); 
    var test2Converted = (Int32)Convert.ChangeType(test2Value, test2Value.GetType()); 

Edycja za komentarz: sprawdzić, czy typ jest IComparable, a następnie za pomocą tego interfejsu zrobić porównania:

if (test1Converted is IComparable && test2Converted is IComparable) 
    { 
     var test1IComparable = (IComparable)test1Converted; 
     var test2IComparable = (IComparable)test2Converted; 

     bool equal = (test1IComparable == test2IComparable); 
    } 
+0

Nie mogę obsłużyć, ponieważ nie wiem jaki jest typ obiektu do czasu wykonania. Może to być ciąg lub inna klasa. –

+0

Ah, racja, cóż, to staje się bardziej skomplikowane :) Możesz przetestować, czy wartości są IComparable; jeśli tak, rzuć na IComparable, a następnie .CompareTo (inne). – glenebob

+0

@SupremeGrandRuler: Jeśli chcesz '32f' na równe' 32L', masz problemy. W przeciwnym razie, po prostu wywołaj 'Equals()'. – SLaks

-1

w moim rozumieniu głównego problemu się tutaj czy nie jesteś świadomy pola klasy Typ testu przed uruchomieniem, i chcesz uniknąć jawnego typowania tekstu na typ całkowity. Zatem porównujemy dwa obiekty test1Converted i test2Converted, prosty sposób zastąpiłby metodę Equals typu bazowego obiektu, który zostanie wywołany w porównaniu ==. W obecnym przypadku test1Converted.Equals(test2Converted) będzie działać, ale jeśli masz typów referencyjnych, a następnie trzeba zastąpić metodę równa się, dla prawidłowego wyniku, w przypadku gdy jest tylko typy wartości, to nie ma problemu

+0

Odpowiadasz na pytanie, które nie zostało zadane przez PO. Zawsze musisz przesłonić 'Equals' na typach innych niż referencje, aby uzyskać równość typu wartości, ale to nie ma nic wspólnego z pytaniem, które zostało zadane. –

+0

@Jason Watkins Nie ma powodu do odrzucenia, moja odpowiedź dostarcza poprawnej odpowiedzi, mówiąc, że można używać równań, a nawet dotknąć rodzaju odniesienia w klasie, wskazać problem w odpowiedzi, a nie dobrze Głos w dół przy kropce szpilki –

+0

Również dla drugiej osoby głosującej, prawdopodobnie nie zrozumiałeś odpowiedzi, przeczytałeś ją i wskazałeś błąd, dokładnie odpowiada na pytanie i wykracza poza –