w odpowiedzi na inne moją odpowiedź, Eric Smith prawidłowo zauważa:
"... bo wymagałoby to niejawnie boks parametr typu odbiornik ...". I tak się dzieje, jeśli zrobisz coś takiego: Func f = 5.ToString; Co jest całkowicie legalne.
Myślenie o tym doprowadziło mnie do nowej odpowiedzi. Wypróbuj to dla rozmiaru:
Zwykłe metody "instancji" na strukturach pobierają, na poziomie CIL, "zarządzany wskaźnik" (typ &
) jako parametr odbiornika. Jest to konieczne, aby metody instancji w strukturach mogły przypisać do pól struktury. Zobacz Partition II, Section 13.3.
Podobnie, metody instancji na klasach przyjmują "odwołanie do obiektu" (typ O
) jako parametr odbiornika (różnica polega na tym, że jest to wskaźnik do zarządzanej sterty i musi być śledzone dla GC).
Ponieważ zarówno CIL &
jak i O
s mogą być (i są) implementowane przez wskaźniki, wszystko jest w porządku do implementacji delegatów. Bez względu na to, czy delegat przechwytuje metodę statyczną, metodę instancji klasy lub metodę instancji struct, wystarczy przekazać wskaźnik do jej _target
do pierwszego argumentu funkcji.
Ale scenariusz, który omawiamy, niszczy to. Metoda statycznego rozszerzania przyjmująca jako argument int
wymaga argumentu CIL typu int32
(patrz rozdział III, sekcja 1.1.1). Oto, co dzieje się z szynami. Nie widzę żadnego powodu, dla którego nie byłby to możliwy do realizacji delegatów, aby zdać sobie sprawę, że tak się dzieje (na przykład, poprzez sprawdzenie metadanych związanych z przechwytywanym MethodInfo) i emitować thunk, który byłby unbox _target
i przekazanie tego jako pierwszego argumentu, ale , nie jest potrzebne dla delegatów do klasycznych metod instancji na strukturach, ponieważ oczekują one wskaźnika i tak nie są i nie pojawiają się (sądząc po przykładzie w mojej wcześniejszej niepoprawnej odpowiedzi) do uprawomocnić się. Oczywiście dany konkretny rodzaj wartości kontrolowałby dokładny charakter wymaganego thunk.
O ile nie brakuje mi bardziej fundamentalnej przeszkody we wdrażaniu (mogę sobie wyobrazić, że na przykład może to stanowić problem dla weryfikatora), wydaje się, że można rozsądnie uzasadnić rozszerzenie środowiska wykonawczego w celu wsparcia tej sprawy, ale wszystkie znaki wskazują na to, że jest to ograniczenie środowiska wykonawczego, a nie kompilatora C# jako takiego.
Czy na pewno nie jest to CS1113? –
Jest; naprawiony. Dzięki – SLaks