我有以下方法:
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
方法之前,如何在不测试类型的情况下保留此类结构?
答案 0 :(得分:13)
为什么不创建接口(IRecordType
),允许RecordType1
和RecordType2
继承接口,然后将每个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,您不仅可以共享某些方法,还可以共享属性和事件。如果RecordType1
和RecordType2
共享多个常见属性,您可以将这些属性添加到interface
,然后在以前需要的地方使用IRecordType
来区分这两个属性使用这些属性,方法或事件。同样,任何这些属性,方法或事件中的代码都允许依赖于特定于对象本身的其他属性,方法,事件或字段。这是面向对象语言( C#)和多态的目的。
编辑:作为评论中讨论的结果,我还想添加有关使用OOP方法(interface
,abstract class
,class
)和StriplingWarrior提出的dynamic
方法建议:
如果您无法访问RecordType1
或RecordType2
的实际实施细节,或者您无法更改应用程序的设计(由于不再依赖{{1和Set(RecordType1)
方法一样,你可能会发现使用Set(RecordType2)
的方法更有成效。还有其他一些我们可能没有想过的选择 - 你总能给出其中一个a。dynamic
方法的缺点是需要.NET 4.0。
此外,还有更多注意事项:如果您确实可以访问dynamic
和RecordType1
实施详细信息,但无法根据定义更改RecordType2
和Set(RecordType1)
,则可以随时修改它们的主体:
Set(RecordType2)
这样可以保留 ENTIRE 应用程序结构,同时还可以减少代码维护并允许多态性。
答案 1 :(得分:7)
如果您肯定,给定集合中的每个项目都与方法签名匹配,您可以将值转换为dynamic
,让运行时找出将其绑定到的内容:
foreach (var record in records)
{
Set((dynamic)record);
}
但是,非常容易出错,我建议你仔细看看你真正想要完成的事情。很可能是一种更好的模式来满足您的需求。