这是否表示它不被支持,还是说虽然被支持但需要进行一些技巧操作?
例如:
class Foo
{
public Foo<T1,T2>(Func<T1,T2> f1,Func<T2,T1> f2)
{
...
}
}
泛型只在构造函数中使用,没有任何依赖于它们的字段/属性,我使用它(泛型)来强制实现 f1 和 f2 的类型相关性。
备注:我发现了解决方法--静态方法Create,但无论如何我都很好奇为什么我在直接方法上遇到问题。
这是否表示它不被支持,还是说虽然被支持但需要进行一些技巧操作?
例如:
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>()
看起来相当难看...
所以,从语义上讲它偶尔会有用 - 但不幸的是,由此产生的丑陋感会抵消这一点。
不支持通用构造函数,但您可以通过定义一个通用的 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;
}
这看起来很好。但是迟早你会想要将 RefCounted<Control>
转换为 RefCounted<Button>
,同时保持两个对象的引用计数,即只有在两个实例都被处理时才处理底层对象。
最好的方法是如果你可以像 C++ 开发人员一样编写代码。
public RefCounted(RefCounted<U> other)
{
...whatever...
}
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();
}
如果您的类中有任何泛型类型的字段,您只能将所有这些类型放入该类中。然而,如果您只想从构造函数中隐藏某些类型,则需要使用上述技巧 - 使用隐藏构造函数将所有内容组合在一起,并定义一个普通的泛型函数来调用该构造函数。
Tuple
为例。 - Jon SkeetList<T>.IndexOf
是一个泛型方法吗,仅仅因为它在一个泛型类型中吗? - Jon Skeet