繁体   English   中英

我可以将成员定义/约束为实现两个接口,而不是泛型吗?

[英]Can I define/constrain a member as implementing two interfaces, without generics?

以下代码显示了我想要做的事情; 也就是说,我想约束anObject,以便它可以用作使用IInterfaceOne或IInterfaceTwo的各种方法的参数,其中两者都不会从另一个继承。

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并没有实现它。

我知道如果我使用泛型我可以约束它们,但我想知道,如果有一种方法可以做到这一点没有泛型?

有没有办法说anObject应该实现IInterfaceOneIInterfaceTwo ,而不使用IInterfaceOneAndTwo

不是你现在的方式。 只有通用约束才具有这种能力。

您可以重写它以使用泛型:

public class UsingImplementation<T>
   where T : IInterface1, IInterface2, new()
{
    T anObject = new T();

    void SomeMethod() {
       anObject.MethodFromInterface1();
    }
}

您还可以使用泛型方法,而不仅仅是泛型类

public void DoSomething<T>(T value)
    where T : IInterface1, IInterface2
{
    value.DoInterface1Things();
    value.DoInterface2Things();
}

要么

public void DoSomething<T>()
    where T : IInterface1, IInterface2, new()
{
    T anObject = new T();
}

你不能在没有泛型的情况下在C#中做到这一点,但是有一个替代的解决方法解决这个问题而没有这里没有提到的泛型 ,可能适合你。 这种风格通常与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原理(控制反转)和依赖注入,您将找到更多与此类似的解决方案。

这样您就不需要创建一个结合InterfaceOne和InterfaceTwo的额外接口,两个。

如果需要,则必须在IInterfaceOne和IInterfaceTwo之间建立逻辑连接,实现类应实现组合接口:

class Implementation : IInterfaceOneAndTwo { ... }

如果这不可能,因为它不是(全部)你的代码,那么你可能不得不重新考虑UsingImplementation。 它根本不适合可用的表面。

“传入”泛型类参数和泛型方法参数可以组合类型,但是没有用于表示“复合”类型的变量或字段的工具。 此外,为了将对象传递给组合多个约束的泛型类型的参数,必须将对象强制转换为实际上实现所有这些约束的类型。 这可能很困难。

例如,假设类FooBar都实现Intf1Intf2 人们希望编写一个函数AddToList<T>(thing as T) where T:Intf1,Intf2 这样的函数将非常乐意接受FooBar类型的对象。 但是,假设有人希望使用这样的函数将所有对象添加到同一个列表中(可能是FooBar和任何其他类型的混合,也恰好实现了Intf1Intf2 )然后再传递这些对象的函数,其参数同样受约束以实现Intf1Intf2 人们可以转换为Foo正好是一个任何对象Foo ,并转换为Bar正好是一个任何对象Bar ,但如果其他类型的可写入也处理Intf1Intf2 ,这将是很难对付他们。

在不使用Reflection或其他类似技巧的情况下,可以稍微笨拙地解决问题。 使用方法ActUpon<thingType>ActUpon(thingType thing) where thingType: Base1, Base2定义接口IActUpon<Base1, Base2>ActUpon<thingType>ActUpon(thingType thing) where thingType: Base1, Base2 这种方法的实现将能够将参数thing传递给需要通用方法参数约束到Base1Base2其他方法。 这种方法最大的困难在于必须为每个可能数量的约束编写单独的代码,并且在许多使用lambda表达式的地方,人们将不得不编写IActUpon...的实现IActUpon...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM