2012-06-28 53 views
4

我已經把自己變成了一隻漁獲22,似乎無法找到我的出路。我試圖實現一個簡單的[Service Locator] [1],由下面示例代碼中的GetInstance方法表示。現在的問題是我得到return語句一個編譯器錯誤說:如何使用泛型基類實現服務定位器模式?

Cannot implicitly convert type 'Cyberspace.SubClass' to 'Cyberspace.BaseClass<T>'

我試着重寫,這樣子類是一個通用類本身,但後來我得到的return語句編譯器錯誤DoSomething方法。

任何人都可以編譯此代碼,保留服務定位器模式的原則,它允許我在GetInstace方法中有一個抽象返回類型?或者我想在這裏獲得一些不可能的東西?

namespace Cyberspace 
{ 
    class BaseClass<T> 
    { 
     BaseClass<T> GetInstance() 
     { 
      return new SubClass(); 
     } 
     virtual T DoSomething() { return default(T); }   
    } 

    class SubClass : BaseClass<OtherClass> 
    { 
     public override OtherClass DoSomething() 
     { 
      var other = new OtherClass { Description = "Generics are hard"}; 
      return other; 
     } 
    } 

    class OtherClass 
    { 
     internal string Description { get; set; } 
    } 
} 

嘗試2:

namespace Cyberspace 
{ 
    class BaseClass<T> 
    { 
     static BaseClass<T> GetInstance() // The "Service Locator" method 
     { 
      return new SubClass<T>(); 
     } 
     internal virtual T DoSomething() { return default(T); }   
    } 

    class SubClass<T> : BaseClass<T> where T: OtherClass 
    { 
     internal override T DoSomething() 
     { 
      var other = new OtherClass { Description = "Generics are hard"}; 
      return (T) other; 
     } 
    } 

    class OtherClass 
    { 
     internal string Description { get; set; } 
    } 
} 

這將產生上線return new SubClass<T>();

The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Cyberspace.SubClass<T>'. There is no boxing conversion or type parameter conversion from 'T' to 'Cyberspace.OtherClass'

+0

有幾個選項。最簡單的方法是將'BaseClass GetInstance()'更改爲'BaseClass GetInstance()'。更復雜的涉及讓SubClass成爲泛型和/或強制約束泛型類型可以通過'where'子句。 http://msdn.microsoft.com/en-us/library/bb384067。aspx –

+0

更改爲BaseClass GetInstance()將該方法鎖定爲僅該特定類。我想要一個通用的方法。我已經研究過使用where約束來通用子類,但是這會在DoSomething方法中產生問題() – Nilzor

回答

1

當使用T聲明類型參數:「我不關心什麼是真正的類型是我只是需要一些,任何類型都叫它T。」。但在你的情況下,它看起來像你想要一個特定的類型。那麼不需要泛型。

class SubClass : BaseClass<OtherClass> 
{ 
    internal override OtherClass DoSomething() 
    { 
     var other = new OtherClass { Description = "Generics are hard"}; 
     return other; 
    } 
} 

爲什麼以下不工作?

 var other = new OtherClass { Description = "Generics are hard"}; 
     return (T) other; 

因爲T可能從OtherClass導出。您不能將OtherClass轉換爲OtherClass派生的類。沒有意義,編譯器足夠聰明,可以抓住它。


在評論的討論導致了以下解決方法:

return (BaseClass<T>)(object)new SubClass(); 

當然,這只是工作,如果該類型在運行時排隊。

+0

它看起來像我想要一個特定類型,因爲該示例僅使用「OtherClass」實例化它。但是,在實際應用程序中實例化時,我將使用其他類而不是OtherClass(雙關語)。 – Nilzor

+0

該觀點適用。爲什麼在SubClass上需要一個類型參數T? – usr

+0

哦,我明白了 - 我還以爲你也是爲了BaseClass。不,我不需要它的子類,但然後BaseClass不會編譯 - 請參閱第一個代碼示例。 – Nilzor

3

我對你真正想做不清下面的錯誤,但我可以告訴你爲什麼編譯錯誤正在發生。

凡是從該方法返回:

BaseClass<T> GetInstance()

必須能夠處理任何類型的T(因爲你沒有類型約束)。​​只能處理一種類型,而不是所有類型。因此你不能退貨。