2012-05-07 23 views
2

TL; DR :(標題放棄它)我可以「在一次轉換中隱式刪除泛型參數從List<T>」?隱式地從列表中刪除泛型參數<T>

一位朋友今天問我是否可以隱式地將List<T>轉換爲非泛型封裝。

var list = new List<_some_type_>(); 
ObjectResult result = list; 

的方法會是這個樣子:

public static implicit operator ObjectResult(List<T> list) { ... } 

顯然,這裏的T沒有定義,並且隱式操作的方法名是類型名稱,ERGO您不能包括通用參數方法名,除非該類型實際上是通用的,即:

class ObjectResult<T> { ... } 

而不是

class ObjectResult { ... } 

我們有一個用戶自定義轉換的約束(我錯過任何?):

  1. 無法轉換或從基類
  2. 無法轉換或從接口。
  3. 必須以兩種類型之一進行轉換。

是什麼讓List<T>這麼難:

  1. List<T>唯一的推導來自Object;因此,我們不得不直接從List<T>
  2. List<T>轉換隻有接口,再次,必須從List<T>
  3. List<T>直接,很明顯,在框架彙編起來,所以,它一定是從我們的包裝

我想到了一個2步驟的解決方案,其中有一箇中間人我們可以轉換(而唯一的中間人List<T>Object,並且由於規則1,這不是一個選項)。

public class ObjectResult 
{ 
    public static implicit operator ObjectResult(WrapperBase arg) { ... } 
} 

public class WrapperBase { } 

public class ObjectResultWrapper<T> : WrapperBase 
{ 
    public static implicit operator ObjectResultWrapper<T>(List<T> arg) { ... } 
} 

然後,調用代碼應該是這樣的:

var list = new List<int>(); 
ObjectResultWrapper<int> wrap = list; 
ObjectResult result = wrap; 

這並不能真正解決問題,這只是一個變通下降T隱含(但在兩個步驟,沒有之一)。此時,使用輔助方法會更容易,並且不會使用用戶定義的轉換。

可能會有人反對隱含地放棄泛型參數的目的 - 我沒有任何其他解釋爲什麼他覺得這很重要。考慮這僅僅是一個學術問題。

+0

這似乎是一個很奇怪的要求不能夠從任何界面轉換。 '列表'實現非通用IList,它不需要知道''。 –

+0

我希望你指出語言的要求 - 我沒有把它做出來......只是澄清你的意見是針對語言,而不是我:) – payo

+1

你能解釋一下你到底想幹什麼嗎? ObjectResult有什麼意義? – svick

回答

2

答案:不,你不能這樣做的隱式演員。

替代方案:

我認爲,最好的辦法是靜態ObjectWrapper.FromList<T>(List<T>)方法。

包裝轉換也是一個選項,雖然沒有那麼優雅。

+0

在我的第二條規則中,我提到接口轉換是不允許的,至少這是我從編譯器得到的:'Testing.ObjectResult.implicit運算符Testing.ObjectResult(System.Collections.Generic.IEnumerable )':用戶定義的轉換來自或從一個接口是不允許的 我使用.net 4.0,visual studio 2010編譯器 – payo

+0

@payo:好吧,看起來你不能那樣做。更新了答案。 –

+0

我同意靜態方法可能是這裏最好的解決方案。但我不會建議雙重演員,這太複雜和混亂。 – svick

1

如何聲明一個靜態的「轉換」函數而不是試圖聲明一個轉換運算符?然後,你可以使用編譯器的類型推斷做這樣的事情(調用轉換方法From):

List<int> list = new List<int>(); 
ObjectResult result = ObjectResult.From(list); 

From方法可能是這樣的:

public class ObjectResult 
{ 
    //... 
    public static ObjectResult From<T>(T arg) { return new ObjectResult<T>(arg); } 
    //... 
} 
public class ObjectResult<T> : ObjectResult 
{ 
    //... 
    public ObjectResult(T obj) { /* ... some implementation ... */ } 
    //... 
} 
+0

我同意這是一個更優雅的解決方案。看起來,這個問題的具體目標是不可能的。 – payo