2016-12-12 48 views
1

委託WaitCallback和Action共享相同的簽名。儘管如此,由於下面的代碼證明,他們不能被視爲同一類型。爲什麼不能將一個Action <Object>委託用作Threadpool的WaitCallback?

static void Main(string[] args) 
{ 
    WaitCallback wcb = (o) => Console.WriteLine("Hello from wcb delegate"); 
    ThreadPool.QueueUserWorkItem(wcb);//works 

    Action<object> action = (o) => Console.WriteLine("Hello from action<object> delegate"); 
    ThreadPool.QueueUserWorkItem(action);//does not compile: Cannot convert from Action<object> to WaitCallback 

    Console.ReadLine(); 
} 

我對這個觀察兩個問題:

1)爲什麼會這樣具有相同簽名但不同的名稱代表不被視爲同一類型?語言設計團隊可能選擇不同還是會導致不一致或其他問題?

2)當Action委託在.Net Framework 2.0中引入的地方時,WaitCallback已經存在。我不知道是不是這種情況,是否有理由引入額外的委託類型WaitCallback而不是使用Action?

謝謝, 亨克

回答

0

從類型系統的角度來看是WaitCallbackAction<object>不同類型和它們之間存在的隱式轉換。因此,您不能使用Action<object>,其中WaitCallback是預期的。引用並作爲代表實際方法,然而,只關心自己的參數列表的兼容性和返回類型,因此不是一個匿名方法,你可以有

private void Foo(object o) { 
    Console.WriteLine("Hello from actual method"); 
} 

及以下線路會不會有問題的工作:

WaitCallback wcb = Foo; 
Action<object> action = Foo; 
ThreadPool.QueueUserWorkItem(Foo); 

注意,在這種情況下該方法的名稱被用於指代它,這被解析並處理不是傳遞了一定類型的變量的方法完全不同。對於後者,你完全處於實際類型和他們的轉換的憐憫之下,代表並不特別。

該規範還包含以下注意事項:

在C#委託類型是名稱等價的,結構上不等同。具體而言,具有相同參數列表和返回類型的兩種不同的委託類型被視爲不同的委託類型。

(警告:投機;我不是在語言設計團隊)因此,這是一個非常明智的選擇,並考慮我寫上面,它可能不是已經不可能讓你要求什麼,但它'd是重載解析如何工作的主要例外。所以我想這個電話是爲了簡化語言而做的。此外,在C#1的日子裏,可能沒有那麼多代表實際上在結構上兼容。

至於你的第二點,他們可能會在這種情況下用Action。作爲示例,請參閱Task.Run方法,該方法使用Action而不是自定義委託。對於不採用或一個參數的操作,似乎是一個相當明顯的情況,不會引入新的委託類型。然而,對於像Action<string, string, int, double>或類似Func類型的東西,我猜有一個可以記錄的實際命名類型比使用通用ActionFunc類型要好得多。

+0

感謝喬伊的精心答覆。你的表述方式讓我更瞭解代表的工作方式。您對方法名稱的解釋稱爲代表,這是一個不錯的獎勵。 – HenkGijsbert

相關問題