2009-06-11 11 views
5

Nie szukam dla porównania dwóch strukturach, które zwraca bool, zastanawiam się, czy istnieje sposób uzyskać, które pola dwóch kodowanym (taką samą strukturę, ale może różne wartości) są różne. Zasadniczo chcę prostszy sposób wykonać następujące czynności:Porównanie wartości dwóch kodowanym w C#

public class Diff 
{ 
    public String VarName; 
    public object Val1; 
    public object Val2; 

    public Diff(String varName, object val1, object val2) 
    { 
     VarName = varName; 
     Val1 = val1; 
     Val2 = val2; 
    } 

    public override string ToString() 
    { 
     return VarName + " differs with values " + Val1 + " and " + Val2; 
    } 
} 

public struct TestStruct 
{ 
    public int ValueOne; 
    public int ValueTwo; 
    public int ValueThree; 

    public List Compare(TestStruct inTestStruct) 
    { 
     List diffs = new List(); 
     if (ValueOne != inTestStruct.ValueOne) 
     { 
      diffs.Add(new Diff("ValueOne", ValueOne, inTestStruct.ValueOne)); 
     } 
     if (ValueTwo != inTestStruct.ValueTwo) 
     { 
      diffs.Add(new Diff("ValueTwo", ValueTwo, inTestStruct.ValueTwo)); 
     } 
     if (ValueThree != inTestStruct.ValueThree) 
     { 
      diffs.Add(new Diff("ValueThree", ValueThree, inTestStruct.ValueThree)); 
     } 
     return diffs; 
    } 
} 

public CompareStructsExample() 
{ 
    TestStruct t1 = new TestStruct(); 
    t1.ValueOne = 1; 
    t1.ValueTwo = 8; 
    t1.ValueThree = 5; 

    TestStruct t2 = new TestStruct(); 
    t2.ValueOne = 3; 
    t2.ValueTwo = 8; 
    t2.ValueThree = 7; 

    List diffs = t1.Compare(t2); 
    foreach (Diff d in diffs) 
    { 
     System.Console.WriteLine(d.ToString()); 
    } 
} 

Zastanawiam się, czy istnieje sposób, aby to zrobić z serializacji jakiejś, lub jeśli jest to jedyny sposób, aby zorientować się, które wartości zostały zmienione . Nawet jeśli istnieje lepszy sposób implementacji funkcji Compare, również bym to zrobił.

+0

Sprawdź moje rozwiązanie linq. Jest naprawdę mały. – johnnycrash

Odpowiedz

10

To można zrobić za pomocą refleksji. Sprawdź przykłady: FieldInfo i PropertyInfo.

MSDN przykład (nieco zmodyfikowane):

Type myType = typeof(TestStruct); 

    // Get the fields of TestStruct. 
    FieldInfo[] myFieldInfo = 
     myType.GetFields(
      BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); 

    Console.WriteLine("\nThe fields of TestStruct are \n"); 

    // Display the field information of TestStruct. 
    for(int i = 0; i < myFieldInfo.Length; i++) 
    { 
     Console.WriteLine("\nName   : {0}", myFieldInfo[i].Name); 
     Console.WriteLine("Declaring Type : {0}", myFieldInfo[i].DeclaringType); 
     Console.WriteLine("IsPublic  : {0}", myFieldInfo[i].IsPublic); 
     Console.WriteLine("MemberType  : {0}", myFieldInfo[i].MemberType); 
     Console.WriteLine("FieldType  : {0}", myFieldInfo[i].FieldType); 
     Console.WriteLine("IsFamily  : {0}", myFieldInfo[i].IsFamily); 
    } 
+0

Tak - poprawna odpowiedź – Dario

+0

Czy istnieje przykład, jak uzyskać rzeczywiste dane? Wygląda na to, że dotyczy to tylko pól/właściwości klasy, czy sugerujesz tylko lepszą implementację metody Compare? – SwDevMan81

+1

Tak jak powiedziałeś, jeśli chcesz wiedzieć, * które * pola są różne, musisz zwrócić jakąś listę (na przykład: Lista ). Może jednak możesz opisać swój cel bardziej szczegółowo, abyśmy mogli zaproponować lepsze rozwiązanie? Na przykład, jeśli była to klasa zamiast struktury, można rozważyć wdrożenie INotifyPropertyChanged interfejs i wypalania zdarzenie, gdy właściwość jest zmieniany - w ten sposób nie będzie musiał sprawdzić wszystkie pola za każdym razem. Wszystko zależy od rzeczywistego celu. – Groo

1

nie mogę jeszcze dodać komentarz, więc w odpowiedzi na SwDevMan81 się tam nieco powyżej^

Jeśli chcesz wartości i masz FieldInfo ...

object val = myFieldInfo[i].GetValue(Obj); 

również

GetFields() zwraca zmienne składowe. Flagi kontrolują, jeśli chcesz publicznych/prywatnych/statycznych członków itp.

GetProperties() zwraca właściwości.

0

Ok, więc korzystając z informacji dla narodów stanowisk, mielibyśmy nowy porównać metodę, która wygląda tak:

public List Compare2(TestStruct inTestStruct) 
{ 
    List diffs = new List(); 

    FieldInfo[] fields = this.GetType().GetFields(); 
    FieldInfo[] fields2 = inTestStruct.GetType().GetFields(); 

    for (int i = 0; i < fields.Length; i++) 
    { 
    object value1 = fields[i].GetValue(this); 
    object value2 = fields2[i].GetValue(inTestStruct); 
    if (!value1.Equals(value2)) 
    { 
     diffs.Add(new Diff(fields[i].Name, value1, value2)); 
    } 
    } 
    return diffs; 
} 

To wydaje się znacząco zmniejszyć wielkość funkcji porównania, ale wciąż mam wszystko klasa Diffs i dodatkowy kod. Czy jest jeszcze prostsza droga niż ta?

+0

Twoje pytanie nie jest wystarczająco szczegółowe, aby pozbyć się klasy diffs, ponieważ nasze zrozumienie wyniku, którego szukasz, jest zbiorem takich obiektów. –

+0

Pytanie z pytaniem, czy istnieje podobny sposób.Na koniec wspomnę, że zadecydowałbym o lepszej implementacji Compare, gdyby to było możliwe – SwDevMan81

+0

Po prostu dodaj to do swojego pytania zamiast dodawać brak odpowiedzi. – TheSoftwareJedi

0

Linq?

public List<string> Compare(TestStruct x, TestStruct y) { 
    return ( 
     from l1 in x.GetType().GetFields() 
     join l2 in y.GetType().GetFields() on l1.Name equals l2.Name 
     where !l1.GetValue(x).Equals(l2.GetValue(y)) 
     select string.Format("{0} {1} {2}", l1.Name, l1.GetValue(x), l2.GetValue(y)) 
    ).ToList(); 
    } 
+0

Niestety nie mogę używać Linq – SwDevMan81

Powiązane problemy