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> {...}
@ AlessandroD'Andria我相信你錯了。另見http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx –
需要注意的是,可以使用代碼契約來表達這一點。通常這是在運行時檢查,但它有可能得到一個編譯時警告(見註釋後):
它是這樣的:
[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 BadFoo
和class AlsoBad
的實現。
GoodFoo.Clone()
由於Contract.Assume(result.GetType() == this.GetType());
的實施沒有任何警告。
然而,代碼契約靜態檢查是(在我看來)仍然是任何東西,但偶爾檢查速度太慢,但您的里程可能會有所不同...
當你執行'ICloneable',你必須返回一個' Foo'或派生的。我在這裏錯過了什麼嗎? –
@YuvalItzchakov我相信的一點是'Foo'可以同樣容易':ICloneable' –
哦,我明白了。謝謝你的澄清@MarcGravell –