【问题标题】:C# - Overloading Templated Method That Has No Arguments [duplicate]C# - 重载没有参数的模板化方法[重复]
【发布时间】:2018-04-12 19:52:38
【问题描述】:

假设我有一个实现WorksWithType<TypeA>WorksWithType<TypeB> 的接口WorksWithType<T> 和类MyClass

如果我的界面看起来像

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

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

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

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

【问题讨论】:

  • 为了实现这一点,您需要方法上的泛型参数,而不是接口上的。
  • @dlatikay:我认为它们肯定是非常密切相关的,但是这个更好,因为它处理 one 方面(只是实现)而不是 1)为什么我会收到有关类型参数隐藏的警告? 2)如何调用我想要的方法? 3)(甚至没有明确说明,部分原因是问题1)我如何实现接口?
  • 拜托,下一个类型你声明一个接口的名称以大写I开头,如IWorksWithType&lt;T&gt;。它是 C# 中的通用标准。

标签: c# oop interface overloading


【解决方案1】:

假设您希望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只能为TypeA类型调用DoSomethingElse和以TypeB 为例。

【讨论】:

    【解决方案2】:

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

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

    (强调我的)

    所以,很遗憾,

    void MyMethod<TypeA>() 
    

    void MyMethod<TypeB>()
    

    不会有不同的签名,因此您不能根据规范同时定义它们:它们的区别仅在于 其类型参数的 type,但不是由它们的类型参数的数量

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

    【讨论】:

    • 更重要的是,void MyMethod&lt;TypeA&gt;() 将引入 TypeA 作为类型 parameter,而我相信 OP 希望有效地将其用作类型 论据。从根本上说,我认为他们正在使用语法来解决问题,但他们使用了错误的语法。
    • 是的,也许我误解了一点 OP 的目标,但希望规格可以为混乱提供一些启示。
    • 我的期望是 OP 真的只是想实现这两个接口,并且陷入冲突。将类型参数命名为 TypeA 会很奇怪,因为实际类型也称为 TypeA。 (你能想象使用TypeB 作为类型参数来调用该方法吗?为一个名为TypeA 的类型参数?令人困惑。)
    • 是的,你展示的显式接口实现很好地满足了这个需求,没有任何疯狂的头痛!
    猜你喜欢
    • 1970-01-01
    • 2019-09-06
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多