public interface ICloneable<T>
{
T Clone();
}
public Foo: ICloneable<Foo>
{
public Foo Clone()
{
//blah
}
}
有没有办法限制T
实现接口的类型?(Foo
在这种情况下)。最好强制执行任何实现ICloneable
以返回其自身的实例,而不是它喜欢的任何随机类型。
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()
看到有关forclass BadFoo
和的实现“确保未经证实”的警告class AlsoBad
。
GoodFoo.Clone()
由于Contract.Assume(result.GetType() == this.GetType());
在其实施中没有警告。
However, Code Contracts Static Checking is (in my opinion) still too slow for anything but occasional checking, but your mileage may vary...