2012-12-30 27 views
0
  • 摘要是否可以在編譯時知道元素類型而無需實現IEnumerable <T>的類?

    忽略一個對象不能表示爲一個陣列的情況下,是有可能定義一個擴展(靜態)方法等:

    public static ? ToArray<TSource>(this TSource source); 
    

    並返回一個對象,如果陣列它由任何一系列元素組成?如果是的話,?會是什麼?

  • 解釋

    我已經想過了以下聲明:

    public static TElement[] ToArray<TElement>(this IEnumerable<TElement> source); 
    public static ? ToArray<TSource>(this IEnumerable source); 
    

    但我不能假設一個未知的類必須實施IEnumerable<T>IEnumerable。我甚至無法定義?,因爲它只是IEnumerable,它不在泛型定義中。

    而且我也想過Array類:

    public static Array ToArray<TSource>(this TSource source); 
    

    但是,這意味着元素類型是在編譯時未知。

    所以我想知道是否有可能知道編譯時的元素類型沒有一個類實現IEnumerable<T>

+0

查看通用約束,如MSDN上所述。這可能會指向你正確的方向。 http://msdn.microsoft.com/en-us/library/d5x73970(v=vs.80).aspx –

+1

如果該類未實現IEnumerable 或IEnumerable,那麼任何人都無法找到它的「元素「?如果沒有實現IEnumerable,你會如何將類描述爲具有「元素」?即使一個類定義了一個'[int index]'索引器,也沒有預定義的方式來確定允許的索引是什麼。 – JLRishe

+0

因爲我的英文很差。如果我後來發現可能導致誤解的內容,我會回滾並嘗試糾正。這是你的問題的答案嗎? –

回答

1

不幸的是,IEnumerator早於泛型,所以它攜帶它沒有類型信息;只是一個IEnumerator GetEnumerator()使String不那麼吸引人的力量,試圖迫使你想要實現這個通用的實現。

這是一個很長的時間,因爲我已經做了C#但我想:

public static TElement ToArray<TSource>(this IEnumerable<TElement> source); 

...應該是罰款:

public static TElement[] ToArray<TElement>(this IEnumerable<TElement> source); 

重要的事情要記住關於延長方法是他們只是語法糖。他們實際上並沒有呆在周圍,或者被注入到他們裝飾的類型中。它們在編譯時被替換爲靜態方法調用。您的續航方式的續航里程將會與不同。

+2

在「公共靜態」的情況下? ToArray (this IEnumerable source);''你根本就不能獲得類型特定於'object []'的東西,因爲IEnumerable'對其GetEnumerator'方法沒有限制,而是返回的實例實現'IEnumerator'。這並不意味着元素類型在編譯時是不可推導的,它只是意味着'IEnumerable'時代沒有機制將其他類型信息轉發到呼叫站點。 – cfeduke

+1

是的,消費者將不得不施放它,關於它沒有兩種方法,並且沒有你[編譯器]不能執行安全演員。將它與具有泛型支持但具有類型擦除的Java相對比 - 作爲泛型類型參數的''''是一個有效的類型描述符,但這僅僅是因爲在編譯期間Java泛型會強制執行類型安全。演員的運行時表演不是問題,如果這是你關心的問題。不安全的演員陣容的運行時安全,是的,這絕對是一個你必須非常關注的問題。 – cfeduke

1

你的問題具體是什麼?如果詢問在編譯時IEnumerable中元素的類型是否總是已知,那麼答案是「否,它並不總是已知的」。非泛型IEnumerable不強制任何元素類型。這就是爲什麼你可以定義任何一個IEnumerable循環foreach

IEnumerable items = GetItems(); 

foreach(SomeClass item in items) 
{ 
    ... 
} 

,但這將引發InvalidCastException如果items的要素之一,不能轉換爲SomeClass

順便說一句,如果你定義這樣的方法:

public static TElement[] MyToArray<TElement>(this IEnumerable<TElement> source); 

然後你就可以 .NET 2.0+稱之爲一個string,因爲string實現了.NET 2.0 IEnumerable<string>和3.0,以及IEnumerable<char>在3.5+以上。實際上,內置到.NET中的.ToArray()擴展可以在string上使用,而無需定義任何內容。

1

它在編譯時不知道,它不能被知道。

例如我能做到:

IEnumerable myCollection; 
string discriminator = Console.ReadLine(); 
if (discriminator == "string") 
{ 
    myCollection = new List<string>{"One", "Two", "Three", "Four"}; 
} 
else 
{ 
    myCollection = new int[]{1, 2, 3, 4}; 
} 

//what should be the type of the elements variable 
var elements = myCollection.ToArray(); 

基本上,根據用戶輸入,myCollection將或者一個List<string>int[],兩種類型,即具有共同幾乎沒有,除了被枚舉的。

因此,爲了您的ToArray的方法來工作,你可以引入類型安全和仿製藥,使用IEnumerable<T>代替IEnumerable,或使用對象的集合,如object[]作爲方法的返回類型。

相關問題