2014-06-23 35 views
1
public interface ICloneable<T> 
{ 
    T Clone(); 
} 

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

有什么办法可以将T约束为实现接口的类型吗? (在这种情况下为Foo)。执行ICloneable来返回它自己的一个实例,而不是任何它幻想的随机类型将是很好的。任何将通用接口约束为实现它的类型的方法?

+0

当你执行'ICloneable ',你必须返回一个' Foo'或派生的。我在这里错过了什么吗? –

+0

@YuvalItzchakov我相信的一点是'Foo'可以同样容易':ICloneable ' –

+0

哦,我明白了。谢谢你的澄清@MarcGravell –

回答

5

不,基本上。你不能用通用约束来做到这一点。此外,您无法阻止他们多次使用不同的T(只要这些T满足任何where约束条件,在这种情况下都不是)。

没有where限制允许限制实施类型。

你还挺有几分可以做到这一点的方法参数的限制,但它不是真正令人满意:

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

@ AlessandroD'Andria我相信你错了。另见http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx –

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

这些都会CAU SE运行时代码合同失效:

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

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

请注意,您可以得到一个编译时实时预警。

如果你做一个完整的代码契约静态检查的编译,你会看到有关的警告“确保未经证实”为Clone()class BadFooclass AlsoBad的实现。

GoodFoo.Clone()由于Contract.Assume(result.GetType() == this.GetType());的实施没有任何警告。

然而,代码契约静态检查是(在我看来)仍然是任何东西,但偶尔检查速度太慢,但您的里程可能会有所不同...

相关问题