2017-11-18 155 views
1

碰撞假設我們有以下4類在C#:的通用擴展方法儘管不同類型的樹木

public class ClassB :ClassA 
{ 

} 

public class ClassA 
{ 
    public string Field { get; set; } 
} 

public class Class2 : Class1 
{ 

} 

public class Class1 
{ 
    public string Field { get; set; } 
} 

ClassA和ClassB的一種類型樹及1級和Class2中形成另一個。

創建以下通用擴展方法,但約束一般類型的特定類型:

public static class ClassAExtensions 
{ 
    public static T Field<T>(this T opts, string field) where T : ClassA 
    { 
     opts.Field = field; 
     return opts; 
    } 
} 
public static class Class1Extensions 
{ 
    public static T Field<T>(this T opts, string field) where T : Class1 
    { 
     opts.Field = field; 
     return opts; 
    } 
} 

理論上下面的代碼應,因爲只有一個單一的擴展方法編譯可以使用:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var instanceB = new ClassB(); 

     instanceB.Field("fed"); 
    } 
} 

但是編譯器返回此錯誤:

The call is ambiguous between the following methods or properties: 'ClassAExtensions.Field(T, string)' and 'Class1Extensions.Field(T, string)'

是這是編譯器還是代碼的錯誤?在我看來,編譯器應該能夠根據類型限制來確定使用哪種擴展方法。

+1

這是擴展方法的矯枉過正。擴展方法用於特定類型,不用作通用方法。如果你真的需要'ClassA'的擴展方法,它應該被聲明爲'public static ClassA Field(this ClassA opts,string field)' –

回答

1

此問題已被詢問次數。通用類型約束不是方法簽名的一部分。

編譯器,解決呼叫時,看到兩個相同的候選人:

ClassAExtensions.Field<T>(this T opts, string field) 
Class1Extensions.Field<T>(this T opts, string field) 

它不能在兩者之間進行選擇,因爲兩者都是同樣有效,因此標籤調用模棱兩可。

現在的問題可能是:這是一個合理的設計?那麼,說得溫和些,對這個問題有不同的看法。閱讀this瞭解更多信息。