2017-08-02 36 views
3

作爲示例,使用String類的Join()方法。當你在 上調用一個字節數組時,例如C#編譯器硬編碼IEnumerable的特殊處理?

byte[] bytes = {3,4,5}; 
string str = string.Join(",", bytes); 

C#編譯器的地圖加入到這個簽名

public static String Join<T>(String separator, IEnumerable<T> values); 

然而,字節[]派生隱式地從類Array不從一般的IEnumerable獲得,而是從非通用IEnumerable的派生,即

public abstract class Array : ICloneable, IList, ICollection, IEnumerable, IStructuralComparable, IStructuralEquatable {...} 

如果我做我自己的接口和類,類似這種情況下,同樣的,我會得到 一個編譯器錯誤預期因爲... e根據規則,您不能將從接口IA(非泛型IEnumerable)派生的類 轉換爲從IA派生的接口IB(通用IEnumerable) 。這意味着C#編譯器只是簡單地對特定名稱IEnumerable進行硬編碼。 這解釋了什麼?

+1

沒有IEnumerable的特殊加工,但有陣協方差的特殊處理。 https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/arrays#array-covariance –

+1

'byte []'實際上實現了'IEnumerable '(更具體地說,[它實現'IList '](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/arrays#arrays-and-the-generic-ilist-interface))。魔術不在'IEnumerable'中,而是以數組的方式處理。查看'Array'的元數據不會告訴你任何事情。 –

+0

@ScottChamberlain這裏沒有數組協變。 – Servy

回答

8

然而,字節[]從Array類派生隱含不從一般的IEnumerable獲得,而是從非通用IEnumerable的派生,即

沒錯,但byte[]工具IEnumerable<byte>本身,這是非常有意義的。我想這是一個編譯Foo[]的特定類型的編譯器功能(所以基本上從Array派生的所有東西)。

參見byte[]的實現的接口(使用Type t = typeof(byte[]);獲得,見屬性ImplementedInterfaces):

byte array implemented interfaces

前6個接口可能是從Array,最後5個接口是1-6的通用版本。

+0

有趣的是,'foo []'實現'IReadOnlyList '這一事實似乎沒有被記錄在任何地方。其他接口來自'Array'和'IList '(後者被實現*記錄在案,並且不從'IReadOnlyList '繼承'IList ')。 –

+0

據我所知,這裏有一篇關於此的帖子。 –

-3

數組在CLR中是特殊的。特別是只有引用類型數組是協變的。值類型如byte不是。就是那樣子。 Eric Lippert在十年前做了一篇博客文章。

String.Join匹配byte[]的唯一版本的可用選項是String Join<T>(String, IEnumerable<T>)

byte[]不能轉換到string[]object[]IEnumerable<string>

可用選項...類型的錯誤

String Join(String, IEnumerable<String>) 
String Join(String, Object[]) 
String Join(String, String[]) 
String Join(String, String[], Int32, Int32) 
String Join<T>(String, IEnumerable<T>) 

實施例...

object[] test1 = new byte[0]; 
string[] test2 = new byte[0]; 
IEnumerable<string> test3 = new byte[0]; 
IEnumerable<byte> test4 = new byte[0]; 

...上面編譯器錯誤...

Cannot implicitly convert type 'byte[]' to 'object[]' 
Cannot implicitly convert type 'byte[]' to 'string[]' 
Cannot implicitly convert type 'byte[]' to to 'System.Collections.Generic.IEnumerable<string>' 

更多轉換實例

Foo[] test = new OtherFoo[0]; // allowed 
OtherFoo[] test = new Foo[0]; // not allowed 

public class Foo 
{ 
} 
public class OtherFoo : Foo 
{ 
} 
+0

那麼爲什麼它匹配'IEnumerable '如果它只實現'IEnumerable'?就是那個問題。 –

+0

因爲'System.Byte []'是mscorlib中的一種類型。 'System.Byte [],mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089' –

+0

因此'Foo []'不執行'IEnumerable '? –