实现.Net接口(C#)

Chr*_*eis 3 .net c# interface

可能是一个简单的问题.

我有一个接口(MyInterface)定义一个属性,如下所示:

IList<IMenuItem> MenuCollection { get; }
Run Code Online (Sandbox Code Playgroud)

而实现MyInterface的类

public class MyClass : MyInterface
{
    public ObservableCollection<MenuItemBase> MenuCollection 
    {
       get
       {
           ...
       }
    }
    ....
}
Run Code Online (Sandbox Code Playgroud)

从我读到的内容来看,ObservableCollection继承自一个IList的Collection,我有一个IMIuItem的MenuItemBase类 - 不会满足接口吗?

我想接口必须明确实现?

我也试过这个:

public class MyClass : MyInterface
{
    public IList<IMenuItem> MenuCollection MenuCollection 
    {
       get
       {
           if(_menuCollection == null)
              _menuCollection = new ObservableCollection<MenuItemBase>();
           return _menuCollection as IList<IMenuItem>;
       }
    }
    private ObservableCollection<MenuItemBase> _menuCollection;
}
Run Code Online (Sandbox Code Playgroud)

看起来像一个变通方法的黑客(我确实遇到了一些问题,说没有实例化MenuCollection)来让界面得到满足....有没有更好的方法来实现IInterface1<IInterface2>对象?

我需要这种抽象的原因是因为我正在构建一个prism/unity应用程序,并希望尽可能地将菜单视图模型与显示菜单的功能区ui分离.

Eri*_*ert 7

乔恩是对的; 这与通用方差无关.但是,他没有提到您想要的功能称为返回类型协方差.

也就是说,如果Animal是Giraffe的基本类型,那么返回Animal的接口方法或返回Animal的虚方法可以通过返回Giraffe的方法来实现/专门化.由于每个长颈鹿都是动物,因此合同得以实现.

C#不支持返回类型协方差; 就此而言,CLR也不是.有些语言支持返回类型协方差; 例如,C++就会浮现在脑海中.(C++/CLI实现做了一些偷偷摸摸的技巧来解决CLR的限制.)实现的接口方法的返回类型,属性的类型等都必须完全匹配C#.


Jon*_*Jon 6

这与通用方差无关

关于泛型方差有多个答案.这与示例无关.如果你试图实现定义为一个属性IListArrayList(没有仿制药),你会看到,它仍然是不可能这样做.

正确答案

这种行为是因为如果您可以实现MenuCollection某种类型的属性实现IList<T>(或从中派生,如果它没有被指定为接口),那么这将是可能的:

public interface MyInterface
{
    IList<IMenuItem> MenuCollection { get; set }
}

public class MyClass : MyInterface
{
    // WARNING: Does not count as implementing the interface -- with good reason
    public ObservableCollection<MenuItemBase> MenuCollection { get; set; }
}

var myClass = new MyClass();
var classAsInterface = (MyInterface) myClass; // This is OK of course

classAsInterface.MenuCollection = new List<MenuItemBase>(); // OOPS!!
Run Code Online (Sandbox Code Playgroud)

在最后一行中,您已经为类型的属性分配了一个List<MenuItemBase>(尽管MyInterface可以告诉,因为MyInterface.MenuCollection它是类型IList<MenuItemBase>)ObservableCollection<MenuItemBase>.

当然这不合法,因为List<MenuItemBase>显然不是源于此ObservableCollection<MenuItemBase>.但是如果你能够实现这样的界面,那将是可能的.

  • @Stormenet:显然,语言规则不能根据你是否定义一个setter来改变. (4认同)