样本代码:
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。这段代码工作正常。
我的问题是,为什么方法需要"where T: class“约束?如果删除它,将得到编译时错误:
Argument 2: cannot convert from
'System.Collections.Generic.IEnumerable<T>' to
'System.Collections.Generic.IEnumerable<object>'
我原以为一切都是“对象”,所以没有必要加以约束?
发布于 2016-03-09 21:02:42
之所以需要约束,是因为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);
}
发布于 2016-03-10 04:50:42
您将将T
应用于已经具有相同约束的FileHelperEngine<T>
,T : class
。编译器可以判断,如果您不对您的方法施加相同的约束,那么T
可能对FileHelperEngine<T>
无效。所以这只是为了防止类型不匹配。
https://stackoverflow.com/questions/35907892
复制相似问题