简体   繁体   English

有什么方法可以将通用接口限制为实现它的类型?

[英]Any way to constrain a generic interface to the type that implements it?

public interface ICloneable<T>
{
    T Clone();
}

public Foo: ICloneable<Foo>
{
    public Foo Clone()
    { 
       //blah
    }
}

Is there any way to constrain T to the type that implements the interface? 有什么方法可以将T约束为实现接口的类型? ( Foo in this case). (在这种情况下为Foo )。 It would be nice to enforce anything implementing ICloneable to return an instance of itself, and not any random type it fancies. 最好强制实施任何实现ICloneable以返回其自身的实例,而不是它所希望的任何随机类型。

No, basically. 不,基本上。 You can't do that with generic constraints. 您不能在通用约束下做到这一点。 Also, you can't stop them implementing the interface multiple times with different T (as long as those T satisfy any where constraints, none in this case). 另外,您不能停止使用不同的T多次实现接口(只要那些T满足任何where约束,在这种情况下都不满足)。

There is no where constraint that allows restriction to the implementing type. 没有where约束可以限制实现类型。

You kinda sorta can do it as a method parameter restriction, but it isn't really satisfactory: 可以将它作为方法参数限制来执行,但并不能令人满意:

public static T SuperClone<T>(this T original) where T : ICloneable<T> {...}

Note that it is possible to use Code Contracts to express this. 请注意,可以使用代码合同来表达这一点。 Normally this is checked at runtime but it's possible to get a compile-time warning (see the notes later): 通常,这是在运行时检查的,但是有可能得到编译时警告(请参阅后面的注释):

It goes something like this: 它是这样的:

[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);
    }
}

Then if you have the following class definitions: 然后,如果您具有以下类定义:

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()
    }
}

This will work OK at runtime: 这将在运行时正常运行:

var good = new GoodFoo();
good.Clone();

These will cause runtime Code Contract failures: 这些将导致运行时代码协定失败:

var bad = new BadFoo();
bad.Clone();

var alsoBad = new BadFoo();
alsoBad.Clone();

Note that you can get a compile time time warning. 需要注意的是,你可以得到一个编译时实时预警。

If you do a full Code Contracts Static Checking compile, you will see warnings about "ensures unproven" for the implementations of Clone() for class BadFoo and class AlsoBad . 如果您执行完整的代码合同静态检查编译,您看到有关class BadFooclass AlsoBad class BadFooClone()实现的“确保未经证实”的警告。

There is no warning for GoodFoo.Clone() because of the Contract.Assume(result.GetType() == this.GetType()); 因为有Contract.Assume(result.GetType() == this.GetType());所以没有针对GoodFoo.Clone()警告Contract.Assume(result.GetType() == this.GetType()); in its implementation. 在执行中。

However, Code Contracts Static Checking is (in my opinion) still too slow for anything but occasional checking, but your mileage may vary... 但是,我认为“代码合同静态检查”仍然太慢,除了偶尔检查之外,对于其他任何事情来说,但是您的里程可能会有所不同...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM