public interface ICloneable<T>
{
T Clone();
}
public Foo: ICloneable<Foo>
{
public Foo Clone()
{
//blah
}
}
有没有办法将T
约束到实现接口的类型? (在这种情况下为Foo
)。最好强制执行任何实现ICloneable
的任何东西来返回它自己的实例,而不是它想要的任何随机类型。
答案 0 :(得分:5)
不,基本上。你不能用通用约束来做到这一点。此外,您无法阻止他们使用不同的T
多次实现该界面(只要那些T
满足任何where
约束,在这种情况下都不会。)
没有where
约束允许限制实现类型。
你有点可以做一个方法参数限制,但它并不是真的令人满意:
public static T SuperClone<T>(this T original) where T : ICloneable<T> {...}
答案 1 :(得分:0)
请注意,可以使用代码约定来表达此信息。通常在运行时检查它,但是可以获得编译时警告(请参阅后面的注释):
它是这样的:
[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();
请注意,您可以获得编译时警告。
如果您执行完整的代码合同静态检查编译,您将看到关于&#34的警告;确保未经证实&#34;用于Clone()
和class BadFoo
的{{1}}的实现。
class AlsoBad
没有警告,因为其实施中有GoodFoo.Clone()
。
但是,代码合同静态检查(在我看来)对于除偶尔检查之外的任何事情来说仍然太慢,但您的里程可能会有所不同......