C# - 重载没有参数的模板化方法

时间:2018-04-12 19:52:38

标签: c# oop interface overloading

假设我有一个WorksWithType<T>MyClass类,它实现了WorksWithType<TypeA>WorksWithType<TypeB>

如果我的界面看起来像

public interface WorksWithType<T> {
     void DoSomething(T foo);
     void DoSomethingElse();
}

DoSomething中实现两个不同的MyClass方法重载很容易。

public class MyClass : WorksWithType<TypeA>, WorksWithType<TypeB> {
{
    public void DoSomething(TypeA fooA) { ... } 
    public void DoSomething(TypeB fooB) { ... } 
    ...
}

但是,似乎没有办法实现DoSomethingElse的重载。在我看来,我觉得我应该能够将界面上的签名更改为

void DoSomethingElse<T>();

然后使用

重载该类
public void DoSomethingElse<TypeA>() { ... } 
public void DoSomethingElse<TypeB>() { ... }  

这里有什么正确的方法,如果有的话?

2 个答案:

答案 0 :(得分:3)

假设您希望DoSomethingElse的两个实现不同,则需要使用explicit interface implementation来区分这些调用:

public class TypeA {}
public class TypeB {}

public interface IWorksWithType<T>
{
     void DoSomething(T foo);
     void DoSomethingElse();
}

public class MyClass : IWorksWithType<TypeA>, IWorksWithType<TypeB>
{
    public void DoSomething(TypeA fooA) {}
    public void DoSomething(TypeB fooB) {} 

    // Note the syntax here - this indicates which interface
    // method you're implementing        
    void IWorksWithType<TypeA>.DoSomethingElse() {}
    void IWorksWithType<TypeB>.DoSomethingElse() {}
}

您不必使两者使用显式接口实现。例如:

public class MyClass : IWorksWithType<TypeA>, IWorksWithType<TypeB>
{
    public void DoSomething(TypeA fooA) {}
    public void DoSomething(TypeB fooB) {} 

    // Explicit interface implementation
    void IWorksWithType<TypeA>.DoSomethingElse() {}
    // Implicit interface implementation
    public void DoSomethingElse() {}
}

如果你不需要实现不同,你当然可以有三种方法:

public class MyClass : IWorksWithType<TypeA>, IWorksWithType<TypeB>
{
    public void DoSomething(TypeA fooA) {}
    public void DoSomething(TypeB fooB) {}

    // Implementation of both IWorksWithType<TypeA>.DoSomethingElse()
    // and IWorksWithType<TypeB>.DoSomethingElse()
    public void DoSomethingElse() {}
}

假设您希望类型参数位于接口上。您可以将它放在方法上,但这实际上代表了一个非常不同的界面 - 而且您无法说MyClass只能调用DoSomethingElse例如,类型TypeATypeB

答案 1 :(得分:1)

根据当前的C#规范(草案6)https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/introduction

  

方法的签名在声明方法的类中必须是唯一的。方法的签名由方法的名称,类型参数的数量以及其参数的数量,修饰符和类型组成。方法的签名不包括返回类型

(强调我的)

所以,不幸的是,

void MyMethod<TypeA>() 

void MyMethod<TypeB>()

不会有不同的签名,因此根据规范,您不能同时定义它们:它们的除了类型参数的类型之外,但不是通过类型参数的数字

其他答案已经指出了如何解决这个问题(在我看来,显式接口实现是一个很好的惯用选项)