为什么在这个例子中需要“where T:class”?

时间:2016-03-10 04:55:39

标签: c# .net generics filehelpers

示例代码:

using System.Collections.Generic;
using FileHelpers;

....
private void Save<T>(string destFilename,  IEnumerable<T> data) where T : class    
{
    var engine = new FileHelperEngine((typeof(T)));


    engine.HeaderText = engine.GetFileHeader(); 
    engine.WriteFile(destFilename, data); // XX
}

在第XX行,engine.WriteFile的第二个参数正在等待IEnumerable&lt; object&gt;。这段代码工作正常。

我的问题是,为什么方法需要“where T:class”约束?如果我删除它,我得到编译时错误:

Argument 2: cannot convert from
'System.Collections.Generic.IEnumerable<T>' to
'System.Collections.Generic.IEnumerable<object>'

我原以为一切都是“对象”,所以约束不是必要的?

2 个答案:

答案 0 :(得分:6)

需要约束,因为object仅是引用类型;可以将值类型分配给object的原因是拳击(尽管从技术上讲,所有类型都继承自System.Object)。

但拳击是类型参数方差的一个独立问题;具有无约束T的IEnumerable<T>无法转换为IEnumerable<object>,因为值类型不支持方差。

另外,非通用FileHelperEngine<T>继承的FileHelperEngine(作为FileHelperEngine<object>)也有T : class约束。所以你不会因为只有支持引用类型而没有错过任何功能 - 理论上可以直接使用FileHelperEngine<T>而不通过非泛型类,因为样本中给出的方法是已经通用:

using System.Collections.Generic;
using FileHelpers;

....
private void Save<T>(string destFilename,  IEnumerable<T> data) where T : class    
{
    var engine = new FileHelperEngine<T>();


    engine.HeaderText = engine.GetFileHeader(); 
    engine.WriteFile(destFilename, data);
}

答案 1 :(得分:0)

您已将T应用于已具有相同约束的FileHelperEngine<T> T : class。编译器可以告诉您,如果您不对您的方法施加相同的约束,则T可能对FileHelperEngine<T>无效。 所以它只是防止类型不匹配。