结合通用方法和重载

时间:2015-04-22 15:08:21

标签: c# generics methods types overloading

我有以下方法:

public void Set<T>(IEnumerable<T> records)
{
     foreach (var record in records)
     {
        Set(record);
     }
 }

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

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

    public void Set(RecordType2 record)
    {
        // Some logic applicable to RecordType2 only
    }

希望您可以看到我尝试允许在运行时推断调用哪个Set方法。这&#34;不工作&#34; (即因为期待RecordType1而不会编译。)

问题

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

2 个答案:

答案 0 :(得分:13)

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

public interface IRecordType
{
    void Set(...);
}
public void Set(IEnumerable<IRecordType> records)
{
    foreach (var record in records)
    {
        record.Set(...);
    }
}

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

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

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

编辑:作为评论中讨论的结果,我还想添加有关使用OOP方法(interfaceabstract classclass)和StriplingWarrior提出的dynamic方法建议:

如果您无法访问RecordType1RecordType2的实际实施细节,或者您无法更改应用程序的设计(由于不再依赖{{1和Set(RecordType1)方法一样,你可能会发现使用Set(RecordType2)的方法更有成效。还有其他一些我们可能没有想过的选择 - 你总能给出其中一个a。dynamic方法的缺点是需要.NET 4.0。

此外,还有更多注意事项:如果您确实可以访问dynamicRecordType1实施详细信息,但无法根据定义更改RecordType2Set(RecordType1),则可以随时修改它们的主体:

Set(RecordType2)

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

答案 1 :(得分:7)

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

 foreach (var record in records)
 {
    Set((dynamic)record);
 }

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