讓我們假設我們有兩個不相關的接口約束擴展方法產生ambigious呼叫
public interface IFirst
{
}
public interface ISecond
{
}
而且具有相同名稱的擴展方法,但受限於每個接口。
public static class IFirstExtensions
{
public static void DoIt<TFirst>(this TFirst model)
where TFirst : IFirst
{
}
}
public static class ISecondExtensions
{
public static void DoIt<TSecond>(this TSecond model)
where TSecond : ISecond
{
}
}
當我試圖用IFirst實例的工作:
IFirst first = ...;
first.DoIt();
然後我得到錯誤:
"CS0121 The call is ambiguous between the following methods or properties: 'IFirstExtensions.DoIt(TFirst)' and 'ISecondExtensions.DoIt(TSecond)'".
這很奇怪。看起來這兩種方法在這個範圍內都是可見的。但是,如果我不同他們的名字,如:
public static class IFirstExtensions
{
public static void DoFirst<TFirst>(this TFirst model)
where TFirst : IFirst
{
}
}
public static class ISecondExtensions
{
public static void DoSecond<TSecond>(this TSecond model)
where TSecond : ISecond
{
}
}
然後約束的作品,第二種方法是不可見的募集編譯錯誤:檢測
IFirst first = ...;
first.DoSecond();
所以看起來像這樣的約束條件staisfying作品differenly含糊不清以及打電話時。但在C#規範中,我發現只有一篇與本主題相關的章節嚴格描述了約束是如何工作的。這是編譯器中的錯誤還是我錯過了一些東西?
Foo類從使用不同我講過的無關課程。我會看到我的版本被關閉成簽名,如:Bar(Frob blah),Bar(Blob blah)。這就是爲什麼而不是CS0111編譯沒有問題。如果你看一下MethodInfo-> Signature-> Arguments [0],你會看到在ImplementedInterfaces屬性中具有不同值的絕對不同的類型。所以在運行時簽名是不同的,它包含約束。 – Stan
但你說得對。我錯過了規範中的一點,通用約束官方忽略簽名。這很荒謬。如果我將擴展IFirst/ISecond Inrerfaces - 這沒關係。如果我將這些合同作爲約束 - 事實並非如此。 – Stan
@stan不,簽名是相同的,錯誤是不同的,因爲方法是在不同的類中定義的。當解決呼叫時,兩種方法都在候選集合中,並且這是當識別簽名發出莊稼並且呼叫被標記爲不明確的時刻。之前沒有給出該錯誤,因爲當將其作爲常規靜態方法調用時,您總是可以明確定義實現擴展方法的靜態類。對於實現兩個具有相同方法簽名和兩個不同約束的接口的類,情況也是如此。 – InBetween