简体   繁体   English

声明具体实现具有具体类型的接口

[英]Declare an interface where concrete implementation has concrete types

public interface ISomeInterface
{
    IOut SomeMethod(IIn aIn)
}

public class MyOut : IOut
{
    public string AnExtraProp {get; set;}
}

public class MyIn : IIn
{
    public string AnotherExtraProp {get; set;}    }
}

public class MyConcreteOfSomeInterface : ISomeInterface
{
     public MyOut SomeMethod(MyIn aIn)
     {
     }
} 

Is it possible to have many classes (eg. MyConcreteOfSomeInterface, MyConcrete2OfSomeInterface, ....) implement an interface (eg. ISomeInterface) but yet have parameters of a concrete type (eg. MyIn, MyOut etc.). 是否有可能有许多类(例如,MyConcreteOfSomeInterface,MyConcrete2OfSomeInterface,....)实现一个接口(例如,ISomeInterface)但是具有具体类型的参数(例如,MyIn,MyOut等)。

I realise I could declare: 我意识到我可以宣布:

public interface ISomeInterface<TIn, TOut>
{
    TOut SomeMethod(TIn aIn)
}

but as ISomeInterface will have many methods this will not be practical. 但由于ISomeInterface将有许多方法,这将是不切实际的。 So say I need to add additional methods SomeMethod2 and SomeMethod3 then I would end up with: 所以说我需要添加其他方法SomeMethod2和SomeMethod3然后我最终得到:

public interface ISomeInterface<TIn, TOut, TIn2, TOut2, TIn3, TOut3>
{
    TOut SomeMethod(TIn aIn)
    TOut2 SomeMethod(TIn2 aIn)
    TOut3 SomeMethod(TIn3 aIn)
}

so the declaration becomes unwieldy pretty quickly. 所以宣言很快变得笨拙。

What design pattern can I use to achieve: 我可以使用什么设计模式来实现:

  1. Many concrete classes implementing an interface ISomeInterface AND 许多具体类实现了接口ISomeInterface AND
  2. Using concrete parameters/return values that are implementing the necessary interfaces IIn, IOut? 使用实现必要接口IIn,IOut的具体参数/返回值?

There will be many methods on ISomeInteface with different types for the parameter/interface combos. ISomeInteface上有许多方法,参数/接口组合有不同的类型。

Let's simplify the problem. 让我们简化问题。 Suppose we have: 假设我们有:

class Animal {}
class Giraffe : Animal {}
interface IFoo 
{
  Animal M(); 
}

Can we then have 那我们可以吗?

class C : IFoo
{
  public Giraffe M() => new Giraffe();
}

Unfortunately no. 抱歉不行。 An interface implementation must match exactly . 接口实现必须完全匹配。

Now, you might think "hey, the interface demands that an animal be returned, and I am returning an animal, namely, a giraffe, so what's the problem?" 现在,你可能会认为“嘿,界面要求动物归还,我要归还动物,即长颈鹿,那么问题是什么?”

The answer is that there is no problem. 答案是没有问题。 C# could have a type system where this works, and this feature has been proposed many many many times. C#可以有一个类型系统,这个功能已被提出很多次了。 It's called "return type covariance", and if you do a search here you'll find many questions about it. 它被称为“返回类型协方差”,如果你在这里搜索,你会发现很多关于它的问题。

However C# does NOT have this feature, and so you're out of luck. 但是C#没有这个功能,所以你运气不好。 The best you can do is: 你能做的最好的事情是:

class C : IFoo 
{
  Animal IFoo.M() => this.M();
  public Giraffe M() => new Giraffe();
}

And now you're good. 现在你很好。 The IFoo contract is explicitly implemented, and the public surface of the class has the more specific signature. IFoo合约是明确实现的,并且该类的公共表面具有更具体的签名。

Similarly, what if we had: 同样,如果我们有:

interface IBar() 
{
  void N(Giraffe g); 
}

This is not legal: 这不合法:

class D : IBar
{
  public void N(Animal g) { ... }
}

Again, this would be perfectly sensible. 再次,这将是非常明智的。 IBar requires that DN be a thing you can pass a giraffe to, and DN is a thing that you can pass a giraffe or any animal to. IBar要求DN是你可以通过长颈鹿的东西,DN是你可以通过长颈鹿或任何动物的东西。 But again, C# does not support this feature. 但同样,C#不支持此功能。 This is called formal parameter contravariance and a very small number of programming languages support it. 这称为形式参数逆变,并且极少数编程语言支持它。

Do a search on C# covariance and contravariance for details on what kinds of variance are supported by C#. 做什么类型的变异由C#支持的详细信息,C#协变和逆变的搜索。

Also, note that this would not be typesafe: 另请注意,这不是类型安全的:

interface IBaz 
{
  void P(Animal a);
}
class E : IBaz
{
  public void P(Giraffe g) { } 
}

Because you need to be able to say ((IBaz)(new E())).P(new Tiger()) . 因为你需要能够说((IBaz)(new E())).P(new Tiger()) IBaz says that an implementation must be able to accept any animal, so you cannot implement it with a method that only accepts giraffes. IBaz说实现必须能够接受任何动物,所以你不能用只接受长颈鹿的方法来实现它。 Logically it would be safe for return types to get more specific, but formal parameter types have to get less specific. 从逻辑上讲,返回类型更加具体是安全的,但正式的参数类型必须不那么具体。 That's why it's return type co variance but formal parameter type contra variance, because the direction of convertibility changes in the contra case. 这就是为什么它的返回类型方差,而形式参数类型反对方差,因为可兑换的方向在对比情况下发生变化。

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

相关问题 使用构造函数参数将接口绑定到多个具体实现 - Bind interface to multiple concrete implementation with constructor argument C#接口函数定义的具体实现 - C# interface function definition concrete implementation 如何通过泛型类型获得接口的具体实现? - How to get the concrete implementation of an interface by the generic type? 获得带有通用参数的接口的具体实现 - Get Concrete Implementation of Interface with Generic Parameter 在Ninject中寻找通用接口的具体实现 - Finding a Concrete Implementation of a Generic Interface in Ninject 访问接口,依赖注入的具体实现 - Accessing Concrete Implementation of Interface, Dependency Injection 将具体实现类型转换为通用接口类型 - Convert concrete implementation type to generic interface type 将不同的具体类型映射到接口集合 - Map Different Concrete Types to Collection of Interface 流利的界面构建不同的混凝土类型 - Fluent interface building different concrete types 当我将变量声明为接口,然后为其指定具体类型时,保存的声明类型在哪里? - When I declare a variable as an Interface, and then assign a concrete type to it, where is the declaration type saved?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM