2011-05-08 13 views
46

這編譯:「無法實現接口成員」錯誤時,界面和混凝土是在不同的項目

public interface IMyInterface 
{ 
    event Action<dynamic> OnSomeEvent; 
} 

class MyInterface : IMyInterface 
{ 
    public event Action<dynamic> OnSomeEvent; 
} 

但是,當我在接口和實現不同的項目分開,我得到:

訪問器 'TestProject2.MyInterface.OnSomeEvent.remove' 無法爲類型'TestProject2.MyInterface'實現接口成員 'InterfaceNamespace.IMyInterface.remove_OnSomeEvent(System.Action)' 。 使用顯式接口 實現。

出現這種情況只能用動態參數...

回答

30

良好的漁獲物。這看起來像是可能是 C#編譯器中的一個錯誤 - 我會ping Eric Lippert以查看他的想法。 (dynamic可以是一個有點調皮,有可能是這個錯誤完全好,但無明顯的原因。)

編輯:下面的代碼將出現後所有工作。今天早上我可以發誓我已經開始工作了...我對於發生了什麼事情感到非常困惑。根據Simon的評論,代碼失敗並顯示消息說不支持該語言。

請注意,如果你使用顯式接口實現,它似乎編譯就好了:

// Doesn't actually compile - see edit above 
class MyInterface : IMyInterface 
{ 
    private Action<dynamic> foo; 

    event Action<dynamic> IMyInterface.OnSomeEvent 
    { 
     // TODO (potentially): thread safety 
     add { foo += value; } 
     remove { foo -= value; } 
    } 
} 

編輯:這個答案仍然是出類拔萃...

注你不能指定一個類似現場的事件作爲一個明確實現的事件,即這不起作用:

event Action<dynamic> IMyInterface.OnSomeEvent; 

它提供了以下錯誤信息:

test.cs中(15,39):錯誤CS0071:顯式接口實現的事件必須使用事件訪問語法

如果你只要嘗試更改爲事件訪問器語法,就會得到與原始代碼 相同的錯誤。

請注意,將事件更改爲屬性可以很好地適用於自動實現的屬性實現。

+1

不知編譯器怎麼會知道如何保護覆蓋,然後認識到如何處理動態做,當你從對方編譯項目分開。 – 2011-05-08 10:03:18

+0

有沒有什麼配置讓顯式接口實現工作?我得到一個錯誤CS0682:'ConsoleApplication1.MyInterface.ClassLibrary1.IMyInterface.OnSomeEvent'無法實現'ClassLibrary1.IMyInterface。OnSomeEvent',因爲它不被編譯的語言錯誤支持。 – 2011-05-08 10:28:17

+0

@Simon:你使用的是什麼版本的C#編譯器?動態是在C#4中引入的。 – 2011-05-08 12:27:11

9

感謝您發佈這個問題,並感謝喬恩發送我的方式。我把它放在我們的一位專門研究「動態」的測試人員的調查隊列中。我們會看看我們能否弄清楚這裏發生了什麼。它當然聞起來像臭蟲。

未來,請考慮在connect.microsoft.com上發佈類似這樣的內容;讓測試人員更快速地獲得測試結果,併爲我們提供更好的機制來獲取有關該問題的更多信息。

+0

從這個問題的有趣部分,如果你通過'動態'通過一個泛型T它編譯fine.so公共'接口IMyInterface {事件動作 OnSomeEvent;}'及其正確的實現即使該接口位於不同的程序集中,它也是一個'ns.IMyInterface =新類MyInterface ()'編譯。在T中包裝'dynamic'與直接使用它不同/更嚴格? – 2011-05-09 18:45:04

+0

看到我的回答,我詳細闡述了它。 – 2011-05-09 19:31:09

2

這個答案是對這個有趣的問題進行精心設計。不是一個真正的答案,但是對整個討論的貢獻是對於正常評論來說太小。

我查了幾件事情,這個接口:

namespace DifferentAssemblyNamespace 
{ 
    public interface IBar 
    { 
     event Action<dynamic> OnSomeEvent; 
    } 
} 

及其實施:

// implicit interface implementation 
// generates compile error "Explicit interface implementation" 
public class Foo1 : IBar 
{ 
    private Action<dynamic> foo; 
    public event Action<dynamic> OnSomeEvent 
    { 
     add { foo += value; } 
     remove { foo -= value; } 
    } 
} 

// implicit interface implementation 
// generates compile error "Not supported by the language" 
public class Foo2 : IBar 
{ 
    private Action<dynamic> foo; 

    event Action<dynamic> IBar.OnSomeEvent 
    { 
     add { foo += value; } 
     remove { foo -= value; } 
    } 
} 

行不通,似乎是一個規則不包括其他必要的規則。

但..如果我們調用仿製藥的幫助,並使用類型參數,而不是直接使用dynamic,如:

namespace DifferentAssemblyNamespace 
{ 
    public interface IGenericBar<T> 
    { 
     event Action<T> OnSomeEvent; 
    } 
} 

及其實施。

// implicit interface implementation 
public class Foo3<T> : IGenericBar<T> 
{ 
    private Action<T> foo; 

    event Action<T> IGenericBar<T>.OnSomeEvent 
    { 
     add { foo += value; } 
     remove { foo -= value; } 
    } 
} 

由於某種原因,我們可以建立(因爲它應該)並運行:

/** does build **/ 
IGenericBar<dynamic> f = new Foo3<dynamic>(); 
f.OnSomeEvent += new Action<dynamic>(f_OnSomeEvent); 

看來,類型參數做一些額外的編譯器很滿意。

我不確定發生了什麼,所以我想知道。

假設,高度假設(也許是廢話)

,但目前我把我的兩分錢的 類型的比較,必須有 通過加發/刪除訪問者在 的鏈表持有該事件的目標/方法 。

我敢打賭 編譯器跌倒在 問題,它不能保證什麼 動態的外部組件,從而不能確定一個元素是否已經在列表中或沒有,這是必要的添加或刪除(因此顯式接口實現)

我們都知道它是隻是一位 歸因的對象,但它似乎仍然 ,它需要一個額外的步驟,其中一些 強類型是有保證的,那就是 什麼T還,在編譯時。

/假設,假設高(也許是廢話)