代码之家  ›  专栏  ›  技术社区  ›  Bryan Anderson

有没有一种方法可以声明一个在.Net中实现多个接口的变量?

  •  18
  • Bryan Anderson  · 技术社区  · 14 年前

    类似 this Java question . 我想指定一个变量实现多个接口。例如

    private {IFirstInterface, ISecondInterface} _foo;
    
    public void SetFoo({IFirstInterface, ISecondInterface} value)
    {
        _foo = value;
    }
    

    • 我没有能力将接口添加到大多数将被传递到Foo的类型中。所以我无法创建从IFirstInterface和ISecondInterface继承的第三个接口。
    • 如果可能的话,我希望避免使包含类泛型化,因为Foo的类型与类没有太多关系,而且用户在编译时不太可能知道它。
    • 以后我需要使用foo来访问两个接口中的方法。
    • 我想以一种编译器安全的方式来做这件事,也就是说,在尝试使用接口之前不要试图强制转换到接口。如果foo不能同时实现这两个接口,那么很多功能将无法正常工作。

    这可能吗?

    编辑 :出于各种原因,我曾多次想要这个。在本例中,这是因为我正在将一组属性从ObservableCollections更改为ReadOnlyObservableCollections。我有一个helper类,它创建了从一个源observeCollection到另一个集合的投影。由于ReadOnlyObservableCollection不从ObservableCollection继承,我只需要IList和INotifyCollectionChanged中的操作,所以我希望将源集合存储为这两个接口的组合,而不需要ObservableCollection。

    4 回复  |  直到 7 年前
        1
  •  18
  •   Dan Tao    14 年前

    如果你想约束你的方法 SetFoo 运气:

    public void SetFoo<T>(T value) where T : IFirstInterface, ISecondInterface
    {
        _foo = value;
    }
    

    从现在起,任何时候你想访问 _foo 成员作为这两个接口之一,您只需通过强制转换访问它: (IFirstInterface)_foo (ISecondInterface)_foo 分别是。

    你说过为了编译时的安全,你想避免使用强制转换;但我想,如果你想办法确保 _福 使用初始化 塞特福 在上面,你可以用平和的心态投出你想要的一切。


    我刚刚意识到下面描述的是你在问题中特别提到的东西 没有 想做什么。所以,我说,按照上面的说法。

    _福 对象是类成员(我基于 _ 在变量名中,可以这样定义类:

    class YourClassThatHasAFoo<T> where T : IFirstInterface, ISecondInterface {
        private T _foo;
    
        public void SetFoo(T value) {
            _foo = value;
        }
    }
    

    显然,这是否有意义取决于你的具体情况。您一定要仔细考虑,因为带有这样的约束的类有时会导致您可能没有预料到的问题(例如 现在 必须 获取类型为的参数 T ,而不仅仅是实现两个接口的任何类)。

        2
  •  6
  •   Adam Robinson    14 年前

    不,无法声明性地确保特定实例实现多个接口。

    一个选项可能是使用泛型,尽管这实际上只适用于函数而不是属性。

    public void Foo<T>(T arg)
        where T : IFirstInterface
        where T : ISecondInterface
    {
        ...
    }
    

    ConcreteType bar = new ConcreteType(); // this implements both
    
    Foo(bar);
    
        3
  •  2
  •   binki    8 年前

    可以定义接口,以便以类型安全的方式需要和使用它们的任意组合。关键是定义一个接口ISelf(Of Out T),它的一个成员Self是一个属性,通过该属性,对象将自身返回为T,然后对于每个接口IFoo,声明一个形式为IFoo(Of Out T)的对应泛型,它从IFoo和ISelf(Of T)继承。一个实现ISelf(Wowzo的)、IFoo(Wowzo的)、IBar(Wowzo的)和IBoz(Wowzo的)的类Wowzo将实现IFoo(IBar的)、IBar(IFoo的)、IFoo(IBoz的)(IBar的))、IFoo(IBar的)(IBar的)(IBoz的)(IBar的)等,并且在必要时可以被类型转换成任何这样的类型。如果Thing是IFoo(属于IBar(属于IBoz)),则可以直接将其用作IFoo,或将Thing.Self用作IBar,或将Thing.Self.Self用作IBoz。

    public interface ISelf<out T>
    {
        T Self { get; }
    }
    interface IA { }
    interface IA<T> : IA, ISelf<T> { }
    interface IB { }
    interface IB<T> : IB, ISelf<T> { }
    interface IC { }
    interface IC<T> : IC, ISelf<T> { }
    class ConcreteThing
        : IA<ConcreteThing>
        , IB<ConcreteThing>
        , IC<ConcreteThing>
    {
        public ConcreteThing Self => this;
    }
    public class ReferencingObject
    {
        IA<IB<IC>> Thing { get; }
    
        void Method()
        {
            IA a = Thing;
            IB b = Thing.Self;
            IC c = Thing.Self.Self;
        }
    }
    
        4
  •  2
  •   Lanting    6 年前

    NET中的变量有一个类型,类型可以实现多个接口。像这样:

    public interface Interface1 { }
    public interface Interface2 { }
    public class SupportsMuliple : Interface1, Interface2 { }
    

    但从您的问题来看,似乎您希望让一个变量实现多个接口,而不需要一个实现这些接口的类型。这实际上是不可能的,但是您可以动态生成一个实现接口的类型,并隐藏一个事实,即有一个真正的类型在发挥作用。嘲弄图书馆 moq 这用的是什么 Castle DynamicProxy