c# - 声明具体实现具有具体类型的接口(interface)

标签 c# design-patterns

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)
     {
     }
} 

是否有可能有许多类(例如 MyConcreteOfSomeInterface、MyConcrete2OfSomeInterface 等)实现一个接口(interface)(例如 ISomeInterface)但具有具体类型的参数(例如 MyIn、MyOut 等)。

我意识到我可以声明:

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

但由于 ISomeInterface 将有许多方法,这将不切实际。所以说我需要添加额外的方法 SomeMethod2 和 SomeMethod3 那么我最终会得到:

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

所以声明很快就会变得笨拙。

我可以用什么设计模式来实现:

  1. 许多实现接口(interface) ISomeInterface 的具体类 AND
  2. 使用实现必要接口(interface) IIn、IOut 的具体参数/返回值?

ISomeInteface 上将有许多方法,它们具有不同类型的参数/接口(interface)组合。

最佳答案

让我们简化问题。假设我们有:

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

那我们能不能

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

不幸的是没有。接口(interface)实现必须完全匹配

现在,您可能会想“嘿,界面要求返回动物,而我要返回动物,即长颈鹿,那有什么问题吗?”

答案是没有问题。 C# 可以有一个可用的类型系统,这个特性已经被提出了很多很多次。它称为“返回类型协方差”,如果您在此处进行搜索,您会发现很多关于它的问题。

但是 C# 没有这个功能,所以你运气不好。你能做的最好的事情是:

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

现在你很好了。 IFoo 契约被显式实现,类的公共(public)表面具有更具体的签名。

类似地,如果我们有:

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

这是不合法的:

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

同样,这将是非常明智的。 IBar 要求 D.N 是可以将长颈鹿传递给的东西,而 D.N 是可以将长颈鹿或任何动物传递给的东西。但同样,C# 不支持此功能。这称为形式参数逆变,只有极少数编程语言支持它。

搜索 C# 协变和逆变,了解 C# 支持哪些类型的方差的详细信息。

另外,请注意这不是类型安全的:

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

因为你需要能够说 ((IBaz)(new E())).P(new Tiger())IBaz 说一个实现必须能够接受任何动物,所以你不能用只接受长颈鹿的方法来实现它。从逻辑上讲,返回类型变得更具体是安全的,但形式参数类型必须不那么具体。这就是为什么它是返回类型 co 变体但形式参数类型是 contra 变体的原因,因为在相反情况下可转换性的方向会发生变化。

关于c# - 声明具体实现具有具体类型的接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49290959/

相关文章:

c# - 使用 MvcRazorToPdf 显示页码

c# - 为什么 EvaluateJavaScriptAsync 没有被执行?

c# - 取消选中其中一个子复选框应取消选中 WPF MVVM 模式中的父复选框

C# 通过递归获取层次列表

c# - 如何在 Visual Studio 2015 中将数据库中的一行显示到文本框

java - 责任链记录

javascript - 包装异步 JavaScript 函数以使其同步的模式

c++ - 用于逻辑拆分的非类型模板

angularjs - 为什么 Angular 服务是单例?

c# - "AsyncFuture<T>"还是什么? Future<T> 在后台线程中获得——它是一种模式吗?