作者热门文章
- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
假设你有一个泛型类 Foo
:
public class Foo<T> {
public T Data {
get;
protected set;
}
}
是否可以定义一个仅适用于 T
的构造函数?继承(或是)特定类型。
例如说T
是一个 int
:
public Foo () {
this.Data = 42;
}
应该在编译时 检查类型约束。这可能对优化有用。比如说你有一个 IEnumerable<T>
并且您希望创建一个“缓存”(因为 LINQ 查询可能非常昂贵)。现在如果IEnumerable<T>
已经是 IList<T>
, 不复制数据是有用的。另一方面,如果它真的是一个 LINQ 查询,另一个构造函数可以将数据存储在一个数组中。
作为变通方法,当然可以继承Foo
(例如 IntFoo
)并在那里定义一个构造函数:
public class IntFoo : Foo<int> {
public IntFoo () {
this.Data = 42;
}
}
然而,这种方法的一个问题是 private
数据不可访问(或者必须使其成为 protected
)。是否还有其他一些缺点,或者是否应该以这种方式为特定类型的构造函数建模?
最佳答案
您可以在此处应用一个技巧。它适用于许多场景。
internal static class FooHelper
{
private static class DefaultData<T>
{
public static T Value = default(T);
}
static FooHelper()
{
DefaultData<int>.Value = 42;
DefaultData<string>.Value = "Hello World";
}
// From @JeffreyZhao:
//
// Use a static method to trigger the static constructor automatically,
// or we need to use RuntimeHelpers.RunClassConstructor to make sure
// DefaultData is corrected initialized.
//
// The usage of RuntimeHelpers.RunClassConstructor is kept but commented.
// Using GetDefault<T>() is a better approach since static Foo() would be
// called multiple times for different generic arguments (although there's
// no side affect in this case).
//
// Thanks to @mikez for the suggestion.
public static T GetDefault<T>()
{
return DefaultData<T>.Value;
}
}
public class Foo<T>
{
/* See the comments above.
static Foo()
{
RuntimeHelpers.RunClassConstructor(typeof(FooHelper).TypeHandle);
}
*/
public T Data { get; protected set }
public Foo()
{
Data = FooHelper.GetDefault<T>();
}
}
您可以为有限的类型指定默认值,并且它们的结果将保持默认值。
这个技巧在实践中有多种变化。在我的项目中,我们使用通用的 ITypeConverter<T>
而不是内置 TypeConverter
避免不必要的装箱:
public interface ITypeConverter<T>
{
bool CanConvertTo<TTarget>();
TTarget ConvertTo(T value);
}
可以应用相同的技巧:
public class LongConverter : ITypeConverter<long>
{
private static class Op<TTarget>
{
public static Func<long, TTarget> ConvertTo;
}
static LongConverter()
{
Op<string>.ConvertTo = v => v.ToString();
Op<DateTime>.ConvertTo = v => new DateTime(v);
Op<int>.ConvertTo = v => (int)v;
}
public TTarget ConvertTo<TTarget>(T value)
{
return Op<TTarget>.ConvertTo(value);
}
}
优雅、快速、干净。
关于c# - C# 中的条件泛型类型构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23924407/
我是一名优秀的程序员,十分优秀!