任何将泛型接口约束为实现它的类型的方法

本文关键字:类型 方法 实现 泛型接口 约束 任何 | 更新日期: 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 BadFooclass AlsoBad的实现的"确保未验证"的警告。

GoodFoo.Clone()没有警告,因为Contract.Assume(result.GetType() == this.GetType());在它的实现中。

然而,代码契约静态检查(在我看来)仍然太慢,除了偶尔的检查,但你的里程可能会有所不同…