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

Moe*_*sko 4 .net c# 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
}
Run Code Online (Sandbox Code Playgroud)

在第XX行,engine.WriteFile的第二个参数是期望IEnumerable <object>.这段代码工作正常.

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

Argument 2: cannot convert from
'System.Collections.Generic.IEnumerable<T>' to
'System.Collections.Generic.IEnumerable<object>'
Run Code Online (Sandbox Code Playgroud)

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

Bol*_*ock 6

需要约束,因为它object只是一个引用类型; 可以分配原因值类型object是由于装箱(即使从技术上讲,所有类型都继承System.Object).

但拳击是类型参数方差的一个单独问题; 一个IEnumerable<T>具有不受约束的T不能被转换成IEnumerable<object>因为方差不支持值类型.

另外,FileHelperEngine<T>非泛型FileHelperEngine继承自(as 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);
}
Run Code Online (Sandbox Code Playgroud)