2012-12-03 263 views
0

我希望能夠做的幾類如下:泛型類型和繼承

var obj1 = new MyClass { Id = 1 }; 
var obj2 = new MyClass { Id = 2 }; 
obj1.Compare(obj2); 

我做了如下的擴展方法(inspired by a different question inhere):

public static class ObjExt 
{ 
    public static ICollection<string> Compare<T>(this T obj1, T obj2) 
    { 
     var properties = typeof(T).GetProperties(); 
     var changes = new List<string>(); 

     foreach (var pi in properties) 
     { 
      var value1 = typeof(T).GetProperty(pi.Name).GetValue(obj1, null); 
      var value2 = typeof(T).GetProperty(pi.Name).GetValue(obj2, null); 

      if (value1 != value2 && (value1 == null || !value1.Equals(value2))) 
      { 
       changes.Add(string.Format("Value of {0} changed from <{1}> to <{2}>.", pi.Name, value1, value2)); 
      } 
     } 
     return changes; 
    } 

現在,這個工程如果我在所有想要比較的課程中都製作了一個方法,所以我想我會把它移到一個超級課堂去幹。

public class MyClass 
{ 
    public int Id { get; set; } 

    public ICollection<string> CompareMe<T>(T obj2) 
    { 
     return Compare<T>(obj2); 
    } 
} 

如果我將它移動到一個超類,我得到這個編譯錯誤:

Cannot convert instance type argument 'SuperClass' to 'T'

如果我這樣做,我的超類:

return this.Compare<T>(obj2); 

我得到一個編譯錯誤說:

The type arguments for method 'Compare(T, T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

如何使這個生成器ic在超級課堂?

+3

也許我不明白,但如果你想將你的方法移到你的超類中,爲什麼你需要一個擴展方法? –

+0

好問題!還有更好的解決方案。重構時我沒有想到這一點。謝謝! –

+0

我可以將評論升級爲答案以將其解決? –

回答

1

此擴展方法:

public static bool GenericTest<T>(this T obj1, T obj2) 
{ 
} 

不會編譯,因爲編譯器沒有什麼T真的是線索:有沒有上下文推斷從類型。您需要使用類似where T: SuperClass的東西或將方法參數更改爲this SuperClass obj1, SuperClass obj2

+0

這是有道理的,但然後SuperClass是唯一能夠使用擴展方法的類。如果可能的話,我希望能夠使它更通用。將方法移入SuperClass更有意義(對我而言)。 –

1

不知道你的超類如何看起來。但這種編譯罰款:

public class SuperClass 
{ 
    public bool GenericTest<T>(T obj2) 
    { 
     return ObjExt.GenericTest(obj2, obj2); 
    } 
} 

public class MyClass : SuperClass 
{ 
    public int Id { get; set; } 

    public bool SuperTest<T>(T obj2) 
    { 
     return this.GenericTest<T>(obj2); 
    } 
} 

public static class ObjExt 
{ 
    public static bool GenericTest<T>(this T obj1, T obj2) 
    { 
     return true; 
    } 
} 
+0

GenericTest位於靜態擴展類ObjExt中 - 在MyClass和SuperClass之外。這似乎改變了圖片。 –

+0

@NicolaiSchlenzig你寫了_I我想提取它到一個超級class_。所以我不明白這種擴展方法如何適合圖片。 – Magnus

+0

你說得對。我想我可以保留我的擴展方法,並從我的超類中調用它來避免冗餘代碼。 –

1

您可以在SuperTest方法添加通用約束:

public bool SuperTest<T>(T obj2) where T: SuperClass 
      { 
       return this.GenericTest(obj2); 
      } 

而在extensionmethod與SuperClass替換T

public static bool GenericTest(this SuperClass obj1, SuperClass obj2) 
     { 
      return true; 
     } 

我不知道這是否是你有什麼儘管如此。

+0

我想使它儘可能通用 - 根本不在擴展中使用SuperClass。我想我可以通過在SuperClass中引入一個方法來調用擴展方法。 –

+0

我讀你更新的問題,並給出你的基於反射的實現我不明白你爲什麼需要CompareMe方法。你可以刪除它,並保持一切。 –

+0

這就是我從閱讀馬修尼科爾斯評論得出的結論。然而,他的答案被刪除,所以我不能標記它解決了。 –