任何将泛型接口约束为实现它的类型的方法
本文关键字:类型 方法 实现 泛型接口 约束 任何 | 更新日期: 2023-09-27 18:09:47
public interface ICloneable<T>
{
T Clone();
}
public Foo: ICloneable<Foo>
{
public Foo Clone()
{
//blah
}
}
是否有任何方法来约束T
实现接口的类型?(本例中为Foo
)。这将是很好的强制任何实现ICloneable
返回自己的实例,而不是任何随机类型的幻想。
基本上没有。对于一般约束,你不能这样做。同样,你不能阻止他们用不同的T
多次实现接口(只要那些T
满足任何where
约束,在这种情况下没有)。
没有where
约束允许对实现类型进行限制。
你有点像可以作为一个方法参数限制,但它并不真正令人满意:
public static T SuperClone<T>(this T original) where T : ICloneable<T> {...}
请注意,可以使用代码契约来表达这一点。通常这是在运行时检查的,但也有可能得到编译时警告(参见后面的注释):
它是这样的:
[ContractClass(typeof(CloneableContract<>))]
public interface ICloneable<out T>
{
T Clone();
}
[ContractClassFor(typeof(ICloneable<>))]
internal abstract class CloneableContract<T>: ICloneable<T>
{
public T Clone()
{
Contract.Ensures(Contract.Result<object>() != null);
Contract.Ensures(Contract.Result<object>().GetType() == this.GetType());
return default(T);
}
}
如果你有以下类定义:
public class GoodFoo: ICloneable<GoodFoo>
{
public virtual GoodFoo Clone()
{
var result = new GoodFoo();
Contract.Assume(result.GetType() == this.GetType());
return result;
}
}
public class BadFoo: ICloneable<object>
{
public object Clone()
{
return new object(); // warning : CodeContracts: ensures unproven: Contract.Result<object>().GetType() == this.GetType()
}
}
public class AlsoBad: GoodFoo
{
public override GoodFoo Clone()
{
return new GoodFoo(); // warning : CodeContracts: ensures unproven: Contract.Result<object>().GetType() == this.GetType()
}
}
这将在运行时正常工作:
var good = new GoodFoo();
good.Clone();
这些将导致运行时代码契约失败:
var bad = new BadFoo();
bad.Clone();
var alsoBad = new BadFoo();
alsoBad.Clone();
注意可以获得编译时时间警告。
如果你做一个完整的代码契约静态检查编译,你将看到关于Clone()
对class BadFoo
和class AlsoBad
的实现的"确保未验证"的警告。
GoodFoo.Clone()
没有警告,因为Contract.Assume(result.GetType() == this.GetType());
在它的实现中。
然而,代码契约静态检查(在我看来)仍然太慢,除了偶尔的检查,但你的里程可能会有所不同…