结合通用方法和重载

3 c# generics methods types overloading

我有以下方法:

public void Set<T>(IEnumerable<T> records)
{
     foreach (var record in records)
     {
        Set(record);
     }
 }
Run Code Online (Sandbox Code Playgroud)

我希望Set调用以下任一方法之一,具体取决于T:

    public void Set(RecordType1 record)
    {
        // Some RecordType1 logic
    }

    public void Set(RecordType2 record)
    {
        // Some logic applicable to RecordType2 only
    }
Run Code Online (Sandbox Code Playgroud)

希望您可以看到我正在尝试允许Set在运行时推断调用哪个方法.这"不起作用"(即不会像预期的那样进行编译RecordType1).

在将记录发送到Set方法之前,如何在不测试类型的情况下保留此类结构?

410*_*one 13

为什么不创建一个接口(IRecordType),允许RecordType1RecordType2继承它,然后将每个Set方法的主要逻辑移动到接口.

public interface IRecordType
{
    void Set(...);
}
public void Set(IEnumerable<IRecordType> records)
{
    foreach (var record in records)
    {
        record.Set(...);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一种更易于维护的解决方案.它还允许更好的多态性.

编辑:要查看的资源:https://msdn.microsoft.com/en-us/library/3b5b8ezk%28v=vs.90%29.aspx

此外,小侧边栏:使用interfaces,您不仅可以共享某些方法,还可以共享属性和事件.如果RecordType1RecordType2共享几个常见属性,则可以将这些属性添加到该属性中interface,然后IRecordType在以前需要的任何位置使用,以区分这两个属性,方法或事件.同样地,内部的任何的那些属性,方法和事件代码允许依靠其他属性,方法,事件或特定于对象本身的字段.这是面向对象语言(C#)和多态的目的.

编辑:正如在评论中讨论的结果,我也想补充有关使用OOP的方法(之间的决策更多信息interface,abstract class,class)和dynamicStriplingWarrior建议的方法:

如果你没有获得实际的实施细则RecordType1或者RecordType2,或者你无法改变你的应用程序的设计(由于在该阻挡的依赖Set(RecordType1)Set(RecordType2)方法,你会发现它更富有成效的把他的使用方法dynamic.还有其他选择,我们可能没有想到 - 你总是可以给他们一个去.这种dynamic方法的缺点是它需要.NET 4.0.

此外,还有更多注意事项:如果您确实有权访问RecordType1RecordType2实现详细信息,但无法更改Set(RecordType1),Set(RecordType2)并且就定义而言,您可以随时修改它们的主体:

public void Set(RecordType1 record)
{
    record.Set(...);
}

public void Set(RecordType2 record)
{
    record.Set(...);
}
Run Code Online (Sandbox Code Playgroud)

这样可以保留整个应用程序结构,同时还可以减少代码维护并允许多态性.

  • 你的答案和OP的代码非常不同.OP没有在`T`中调用`Set`方法,而是当前的类.不知道为什么这个被大量投票: (3认同)
  • @SriramSakthivel我知道,OP的方法也不是面向对象的好例子.我的解决方案是最终为OP提供一个更易于维护的项目,不仅仅是对他的问题的回答,而是解决更加不足的问题. (2认同)
  • 这并不总是可行的(如果类型属于第三方).在这种情况下,我们需要使用适配器模式或其他类型.但是,我喜欢你的答案.+1 :) (2认同)

Str*_*ior 7

如果你肯定给定集合中的每个项都与方法签名匹配,你可以将值转换为,dynamic并让运行时找出将它绑定到的内容:

 foreach (var record in records)
 {
    Set((dynamic)record);
 }
Run Code Online (Sandbox Code Playgroud)

但是,这很容易出错,我建议你仔细看看你真正要完成的事情.最有可能是一种更好的模式来满足您的需求.