为什么在此示例中需要 "where T : class"?
Why is "where T : class" required in this example?
示例代码:
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>'
我会认为一切都是 "object",所以约束是不必要的?
需要约束,因为object
只是一个引用类型;可以将值类型分配给 object
的原因是由于装箱(尽管从技术上讲,所有类型都继承自 System.Object
)。
但是装箱与类型参数变化是不同的问题;具有无约束 T 的 IEnumerable<T>
无法转换为 IEnumerable<object>
,因为值类型不支持方差。
顺便说一句,非泛型 FileHelperEngine
继承自(如 FileHelperEngine<object>
)的 FileHelperEngine<T>
也有一个 T : class
约束。因此,由于仅支持引用类型,因此您不会因具有约束而丢失任何功能 - 理论上可以直接使用 FileHelperEngine<T>
而无需通过非泛型 class,因为中给出的方法示例已经是通用的:
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);
}
您要将 T
应用于 FileHelperEngine<T>
,后者已经具有相同的约束 T : class
。编译器可以告诉你,如果你不对你的方法施加相同的约束,那么 T
可能对 FileHelperEngine<T>
无效。
所以它只是防止类型不匹配。
示例代码:
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>'
我会认为一切都是 "object",所以约束是不必要的?
需要约束,因为object
只是一个引用类型;可以将值类型分配给 object
的原因是由于装箱(尽管从技术上讲,所有类型都继承自 System.Object
)。
但是装箱与类型参数变化是不同的问题;具有无约束 T 的 IEnumerable<T>
无法转换为 IEnumerable<object>
,因为值类型不支持方差。
顺便说一句,非泛型 FileHelperEngine
继承自(如 FileHelperEngine<object>
)的 FileHelperEngine<T>
也有一个 T : class
约束。因此,由于仅支持引用类型,因此您不会因具有约束而丢失任何功能 - 理论上可以直接使用 FileHelperEngine<T>
而无需通过非泛型 class,因为中给出的方法示例已经是通用的:
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);
}
您要将 T
应用于 FileHelperEngine<T>
,后者已经具有相同的约束 T : class
。编译器可以告诉你,如果你不对你的方法施加相同的约束,那么 T
可能对 FileHelperEngine<T>
无效。
所以它只是防止类型不匹配。