提问人:greenoldman 提问时间:8/31/2010 更新时间:11/8/2022 访问量:51628
是否支持非泛型类中的泛型构造函数?
Is generic constructor in non-generic class supported?
问:
它不支持吗,它是否受支持,但我必须做一些技巧?
例:
class Foo
{
public Foo<T1,T2>(Func<T1,T2> f1,Func<T2,T1> f2)
{
...
}
}
泛型仅在构造函数中使用,没有依赖于它们的字段/属性,我使用它(泛型)来强制执行 f1 和 f2 的类型关联。
备注:我找到了解决方法 - 静态方法Create,但无论如何我很好奇为什么我对直接方法有问题。
答:
否,泛型或非泛型类都不支持泛型构造函数。同样,不支持泛型事件、属性和终结器。
只是偶尔我同意它会很方便 - 但语法看起来很糟糕。例如,假设您有:
public class Foo<T> {}
public class Foo
{
public Foo<T>() {}
}
什么会
new Foo<string>()
男孩调用非泛型类的泛型构造函数,还是泛型类的普通构造函数?你必须以某种方式区分它们,这将是混乱的:(
同样,考虑泛型类中的泛型构造函数:
public class Foo<TClass>
{
public Foo<TConstructor>() {}
}
你会如何称呼构造函数?希望我们都能同意:
new Foo<string><int>()
真是太狰狞了......
所以是的,从语义上讲,它偶尔会有用——但不幸的是,由此产生的丑陋抵消了这一点。
评论
Tuple
List<T>.IndexOf
不支持泛型构造函数,但您可以通过简单地定义一个返回新方法的泛型方法来解决这个问题:static
Foo
class Foo
{
public static Foo CreateFromFuncs<T1,T2>(Func<T1,T2> f1,Func<T2,T1> f2)
{
...
}
}
其使用方式如下:
// create generic dependencies
var func1 = new Func<byte, string>(...);
var func2 = new Func<string, byte>(...);
// create nongeneric Foo from dependencies
Foo myFoo = Foo.CreateFromFuncs<byte, string>(func1, func2);
下面是一个实际示例,说明您希望如何拥有额外的构造函数类型参数以及解决方法。
我将介绍一个简单的包装器:RefCounted
IDisposable
public class RefCounted<T> where T : IDisposable
{
public RefCounted(T value)
{
innerValue = value;
refCount = 1;
}
public void AddRef()
{
Interlocked.Increment(ref refCount);
}
public void Dispose()
{
if(InterlockedDecrement(ref refCount)<=0)
innerValue.Dispose();
}
private int refCount;
private readonly innerValue;
}
这似乎很好。但迟早你希望将 to 同时保持两个对象引用计数,即仅当两个实例都被处置时才释放基础对象。RefCounted<Control>
RefCounted<Button>
最好的方法是你可以写(就像C++人可以做的那样)
public RefCounted(RefCounted<U> other)
{
...whatever...
}
但 C# 不允许这样做。所以解决方案是间接使用。
private readonly Func<T> valueProvider;
private readonly Action disposer;
private RefCounted(Func<T> value_provider, Action disposer)
{
this.valueProvider = value_provider;
this.disposer = disposer;
}
public RefCounted(T value) : this(() => value, value.Dispose)
{
}
public RefCounted<U> Cast<U>() where U : T
{
AddRef();
return new RefCounted<U>(() => (U)(valueProvider()),this.Dispose);
}
public void Dispose(){
if(InterlockedDecrement(ref refCount)<=0)
disposer();
}
如果您的类具有任何泛型类型的字段,则您别无选择,只能将所有这些类型放入该类中。但是,如果您只想从构造函数中隐藏某种类型,则需要使用上述技巧 - 使用隐藏的构造函数将所有内容放在一起,并定义一个普通的泛型函数来调用该构造函数。
评论