我可以将成员定义/约束为实现两个接口,而不是generics吗?
以下代码显示了我想要做的事情; 也就是说,我想约束anObject,以便它可以用作各种方法的参数,使用IInterfaceOne或IInterfaceTwo,其中两者都不从另一个inheritance。
public interface IInterfaceOne { } public interface IInterfaceTwo { } public class Implementation : IInterfaceOne, IInterfaceTwo { } public interface IInterfaceOneAndTwo : IInterfaceOne, IInterfaceTwo { } public class UsingImplementation { IInterfaceOneAndTwo anObject = (IInterfaceOneAndTwo)(new Implementation()); //fails because Implementation doesnt acctually implement IInterfaceOneAndTwo }
但是这个例子失败了,因为IInterfaceOneAndTwo本身就是一个接口,而Implementation并没有实现它。
我知道如果我使用generics我可以约束它们,但我想知道,如果有一种方法可以做到这一点没有generics?
有没有办法说anObject
应该实现IInterfaceOne
和IInterfaceTwo
,而不使用IInterfaceOneAndTwo
?
“传入”generics类参数和generics方法参数可以组合类型,但是没有用于表示“复合”类型的变量或字段的工具。 此外,为了将对象传递给组合多个约束的generics类型的参数,必须将对象强制转换为实际上实现所有这些约束的类型。 这可能很困难。
例如,假设类Foo
和Bar
都实现Intf1
和Intf2
。 人们希望编写一个函数AddToList
。 这样的函数将非常乐意接受Foo
或Bar
类型的对象。 但是,假设有人希望使用这样的函数将所有对象添加到同一个列表中(可能是Foo
, Bar
和任何其他类型的混合,也恰好实现了Intf1
和Intf2
),然后再传递这些对象的函数,其参数同样受约束以实现Intf1
和Intf2
。 有人可以将任何恰好是Foo
对象Intf2
为Foo
,然后将任何恰好是Bar
对象Intf2
为Bar
,但是如果写入其他类型也会处理Intf1
和Intf2
,则很难处理它们。
在不使用Reflection或其他类似技巧的情况下,有点笨拙地解决问题是可能的。 使用方法ActUpon
定义接口IActUpon
, ActUpon
。 这种方法的实现将能够将参数thing
传递给需要通用方法参数约束到Base1
和Base2
其他方法。 这种方法的最大困难在于必须为每个可能的约束数量编写单独的代码,并且在许多地方使用lambda表达式的情况下,必须编写IActUpon...
的实现IActUpon...
不是你现在的方式。 只有通用约束才具备这种能力。
你可以重写它来使用generics:
public class UsingImplementation where T : IInterface1, IInterface2, new() { T anObject = new T(); void SomeMethod() { anObject.MethodFromInterface1(); } }
您还可以使用generics方法,而不仅仅是generics类
public void DoSomething(T value) where T : IInterface1, IInterface2 { value.DoInterface1Things(); value.DoInterface2Things(); }
要么
public void DoSomething() where T : IInterface1, IInterface2, new() { T anObject = new T(); }
你不能在没有generics的情况下在C#中做到这一点但是有一个替代的解决方法来解决这个问题而没有这里没有提到的generics并且可能适合你。 这种风格通常与IoC原则一起使用。 您可以两次注入相同的对象。 让我更改你的样本……
public interface IInterfaceOne { void Hello(); } public interface IInterfaceTwo { void World(); } public class Implementation : IInterfaceOne, IInterfaceTwo { public void Hello() { }; public void World() { }; } public class UsingImplementation { private readonly IInterfaceOne one; private readonly IInterfaceTwo two; public UsingImplentation(IInterfaceOne one, IInterfaceTwo two) { this.one = one; this.two = two; } // do the stuff you want to do with an IInterfaceOne using field one public DoSomeThingWithOne() { one.Hello(); } // do the stuff you want to do with an IInterfaceTwo using field two public DoSomeThingWithTwo() { two.World(); } }
然后你可以用这种方式连接东西:
var oneAndTwo = new Implementation(); var a = new UsingImplementation(oneAndTwo, oneAndTwo); // operates on the first param (which is the same as the second) a.DoSomeThingWithOne(); // operates on the second param (which is the same as the first) a.DoSomeThingWithTwo();
查看IoC原理(控制反转)和dependency injection,您将找到更多与此类似的解决方案。
这样您就不需要创建一个结合InterfaceOne和InterfaceTwo的额外接口,两个。
如果需要,则必须在IInterfaceOne和IInterfaceTwo之间建立逻辑连接,实现类应实现组合接口:
class Implementation : IInterfaceOneAndTwo { ... }
如果这是不可能的,因为它不是(全部)你的代码,那么你可能不得不重新考虑UsingImplementation。 它根本不适合可用的表面。