2009-12-06 28 views
0

我喜歡將我的定義與我的實現分開。我有一個接口實體:限制泛型在特定情況下失敗

public interface Entity<E> where E : Entity<E> 
{ 
    EntityId EntityId { get; } 

    bool ReadOnly { get; } 

    void FailIfReadOnly(); 

    E Copy(); 
} 

E是實際的實體類型,如Customer:

public interface Customer : Entity<Customer> 
{ 
} 

我的問題是FailIfReadOnly(執行):如果只讀== true,則拋出一個EntityIsReadOnlyException。

public class EntityIsReadOnlyException<E> where E : Entity<E> 
{ 
    public EntityIsReadOnlyException(E entity) 
     : base(string.Format("Entity {0} is read only", entity.EntityId)) 
    { 
    } 
} 

public class EntityImpl<E> : Entity<E> where E : Entity<E> 
{ 
    public EntityImpl(E other) 
    { 
    } 

    public bool ReadOnly 
    { 
     get; 
     protected set; 
    } 

    public void FailIfReadOnly() 
    { 
     if (! ReadOnly) throw new EntityIsReadOnlyException<E>(this); 
    } 
} 

throw new EntityIsReadOnlyException<E>(this);導致編譯錯誤:

The best overloaded method match for 'EntityIsReadOnlyException.EntityIsReadOnlyException(E)' has some invalid arguments

Argument '1': cannot convert from 'EntityImpl' to 'E'

我可以這樣做:

EntityIsReadOnlyExcetion<Customer> exc = new EntityIsReadOnlyException<Customer>(customerImpl); 

,甚至:

Entity<E> entity = new EntityImpl<E>(this); 

但不是:

EntityIsReadOnlyException<E> exc = new EntityIsReadOnlyException<E>(this); 

在這兩種情況下,E僅限於實體的子類。我的問題是,爲什麼我得到這個編譯錯誤?這可能很簡單。

+0

接口上「where E:Entity 」的用途是什麼? – 2009-12-06 21:48:57

+1

這是一個遞歸定義是不是? IE類型限制是一個實體>? 這甚至可能嗎? – Spence 2009-12-06 21:57:20

+0

@marcgravell - 通常這種遞歸類型限制的目的是在基類中實現可以返回派生類型的克隆或副本。 – x0n 2009-12-06 22:05:35

回答

4

首先,你的異常類不從異常派生:

public class EntityIsReadOnlyException<E> : Exception where E : Entity<E> 

然後注意到您的異常的構造函數不採取Entity<E>作爲參數,而是E.

方法1:改變你的構造函數採取Entity<E>

public EntityIsReadOnlyException(Entity<E> entity) 

方法2:通過other您例外:

E other; 
public EntityImpl(E other) 
{ 
    this.other = other; 
} 

... 

if (ReadOnly) throw new EntityIsReadOnlyException<E>(other); 

非工作方法:嘗試施放此到E:

if (ReadOnly) throw new EntityIsReadOnlyException<E>((E)(Entity<E>)other); 

這將編譯,但在運行時失敗,因爲你的實施對象是不一樣的類型作爲參數E和不能投給它。

另一個小問題:您的if (!ReadOnly)檢查是錯誤的。它應該是if (ReadOnly)

0

嗯......

錯誤消息是相當清楚的:你不能轉換EntityImpl到E ...只是因爲沒有實體基於E的,也不執行轉換操作符...

您可以使用馬克的方式或重寫實體接口作爲抽象類與隱式運算符E(實體實體)和至少有一個參數E實例的構造函數。所以你所有派生類都可以做到這一點。