这两个看似相似的声明有什么区别? 你何时会选择一种语法而不是另一种?
有没有具体的理由选择其中一个?
两种情况都会导致任何性能损失吗?
public void Import<T>(
Func<IEnumerable<T>> getFiles, Action<T> import)
where T : IFileInfo
{
// Import files retrieved through "getFiles"
}
public void Import(
Func<IEnumerable<IFileInfo>> getFiles, Action<IFileInfo> import)
{
// Import files retrieved through "getFiles"
}
答案 0 :(得分:3)
不同之处在于,第一个允许您传递使用更具体类型实现IFileInfo
的内容。例如:
Func<IEnumerable<SpecialFileInfo>> lister = () => ListFiles();
Import(lister, file => Console.WriteLine(file.SpecialProperty));
(其中SpecialProperty
是SpecialFileInfo
但不存在IFileInfo
的属性。)您无法使用后一种形式执行此操作。
泛型方法和类型的执行时间损失非常小 - 对于不同的每个值类型T
类型参数,它将被JIT一次(不要忘记值类型可以实现IFileInfo
)并且对于所有引用类型(即,一旦它被JIT或一个引用类型,它将不需要再次被JIT)。这几乎可以肯定在您的实际应用中可以忽略不计。
答案 1 :(得分:2)
虽然这些问题已经得到解答:也许您希望采用限制较少的解决方案:
public void Import<T,S>(
Func<IEnumerable<S>> getFiles, Action<T> import)
where T : IFileInfo
where S : T
{
// Import files retrieved through "getFiles"
}
这个允许传递Action<IFileInfo>
和Func<IEnumerable<ConcreteFileInfo>>
。
答案 2 :(得分:1)
没有任何运行时性能损失 - 这些都是在为代码生成IL时由编译器处理的。
至于语法,我认为第二个更清楚你只对IFileInfo接口感兴趣。
答案 3 :(得分:1)
在这种情况下没有太大的区别,但是你想进一步限制它,例如你希望T有一个默认的无参数构造函数。你只能这样做:
public void Import<T>(
Func<IEnumerable<T>> getFiles, Action<T> import)
where T : IFileInfo, new()
{
// Import files retrieved through "getFiles"
}
答案 4 :(得分:1)
您不会注意到功能方面的差异,但您可以在呼叫方看到一个。
public class MyFileInfo : IFileInfo
{
public string MyString { get; set; }
}
Import<MyFileInfo>(files,
(mfi) => Console.WriteLine("Import {0}", mfi.MyString));