2015-11-10 12 views
5

Die Kommentare im source code für IList, IEnumerable und ICollection bereitgestellt sagtZweck von TypeDependencyAttribute ("System.SZArrayHelper") für IList <T>, IEnumerable <T> und ICollection <T>?

Beachten Sie, dass T[] : IList<T>, und wir wollen, um zu gewährleisten, wenn Sie IList<YourValueType> verwenden, stellen wir sicher, ein YourValueType[] ohne jitting verwendet werden kann. Daher die TypeDependencyAttribute auf SZArrayHelper. Dies ist ein spezieller Hack intern - siehe VM \ compile.cpp.

Warum IList<T> enthalten eine Abhängigkeit von SZArrayHelper?. Ich verstehe, dass SZArrayHelper ist ein CLR-Wrapper um ein Array, das die IList<T> Schnittstelle implementiert, aber ich bekomme nicht das vollständige Bild, warum diese beiden miteinander verbunden sind.

Und wie stellt es sicher YourValueType[] kann ohne jitting verwendet werden.?

+0

Wahrscheinlich nicht tun :) da 99,9% der Sammlungen eine Anordnung zur Speicherung auf einer bestimmten Ebene zu verwenden, so dass es "vernünftig, diese Abhängigkeit zu verlangen. Ist das ein Problem oder bist du nur neugierig? –

+0

@DStandley: Neugierig .. aber wieder wie stellt es YourValueType [] kann ohne jitting verwendet werden.? – NullReference

+1

Es geht nicht wirklich um 'YourValueType []' * selbst *. Es geht darum, es zu verwenden, wenn es in die entsprechende generische Schnittstelle umgewandelt wird. 'int []' * * implementiert * IEnumerable nicht wirklich .GetEnumerator', obwohl es so erscheint, als ob es tat - die tatsächliche Implementierung ist in dieser mysteriösen 'SZArrayHelper' Klasse. – Luaan

Antwort

9

Es ist ein Hack in der JIT, wie in Ihrem Zitat erwähnt. Wenn die VM feststellt, dass es eine TypeDependency unter SZArrayHelper gibt, behandelt sie die Klasse anders, so dass effizienterer Code verwendet werden kann.

an der entsprechenden Code-Suche in der VM (Anmerkung, die ich verwende eine ältere, öffentlich zugängliche Version hier - nicht die tatsächliche .NET VM):

einen Aufruf an ein Array durch IList (oder IEnumerable oder ICollection) muss speziell behandelt werden. Diese Schnittstellen sind „Magie“ (vor allem aufgrund Workingset betroffen - sie auf Verlangen werden intern obwohl semantisch, sind diese statischen Schnittstellen.)

Arrays sind ein bisschen wie ein Hack in .NET in der erster Platz. Wenn die generischen Schnittstellen hinzugefügt wurden, stellte dies ein kleines Problem dar - zum Beispiel int[] ist ein Array, aber es ist auch ein spezieller Typ und ein Array von int; Dies erlaubte Arrays, generisch zu sein, bevor echte generische Typen hinzugefügt wurden.

Jetzt sehen wir uns ein konkretes Beispiel an. Sie haben eine int[], und Sie möchten es in LINQ verwenden. Da int[]IEnumerable<int> implementiert, es gibt Ihnen die volle Leistung von LINQ aus der Box, und Sie können so etwas schreiben:

var positiveNumbers = numbers.Where(i => i > 0); 

Von C# 's Sicht, gibt es kein Problem. Von dem Punkt der Interna der VM ist diese jedoch ein großes Problem, weil int[] nicht tatsächlich implementieren IEnumerable<int>! Auch nach der Einführung von Generics in .NET (und C#) werden Arrays immer noch auf die alte Art und Weise behandelt.

Der Hack soll SZArrayHelper verwenden, um mit all diesen generischen Methoden umzugehen. So ruft zum Beispiel WhereGetEnumerator intern auf der IEnumerable<int>. Die VM stellt fest, dass Sie versuchen, GetEnumerator in einem Array aufzurufen, und anstatt GetEnumerator auf der Array-Instanz virtuell zu verteilen, leitet sie den Aufruf an SZArrayHelper.GetEnumerator<int>() um.

Dies ist ein riesige Hack - wenn Sie für SZArrayHelper auf dem Referenzcode anschauen, werden Sie Tonnen von Warnungen finden - zum Beispiel die GetEnumerator<int> Methode ist eine Instanzmethode, aber es ist this Argument ist eigentlich die Array (z. B. int[]), nicht SZArrayHelper.

Aber es erlaubt uns Arrays zu behandeln, als ob sie tatsächlich alle jene generische Schnittstellen umgesetzt haben - obwohl sie

+0

Brilliant !!!. Aber nie so. – NullReference

Verwandte Themen