Non c'è implementazione di IEnumerable e di altri!
No. Eppure, IList<Stream> streamList = fsArray;
funzionerà. Ed è possibile utilizzare streamList
come previsto, anche se con eccezioni di runtime se si tenta di eseguire qualcosa non valido su un array (purché l'array sia a base zero e abbia una dimensione singola - "SZ array" in Microsoft parlance- altrimenti non è permesso).
Vuoi vedere qualcosa di peggio?
var listMap = typeof(List<FileStream>).GetInterfaceMap(typeof(IList<FileStream>)); // This works fine.
var arrMap = typeof(typeof(FileStream[]).GetInterfaceMap(typeof(IList<FileStream>)); // This throws `ArgumentException`
Quindi, a questo proposito, FileStream[]
non ha nemmeno implementare IList<FileStream>
; se lo fa allora sicuramente la linea sopra dovrebbe funzionare.
Otteniamo un indizio interessante da. NET 4.0. Prima di questo, il ArgumentException
avrebbe un messaggio di "Interface not found"
, lo stesso come se avessimo cercato di ottenere quell'interfaccia su int
o string[]
. Ora è "Interface maps for generic interfaces on arrays cannot be retrived."
[sic]
E ci dà anche questo se proviamo a ottenere la mappa di interfaccia per IList<Stream>
ma non per un'interfaccia completamente non supportata come IList<bool>
.
Qui sta succedendo qualcosa di insolito.
E quello che è, è che FileStream[]
non supporta affatto alcuna interfaccia generica, nello stesso modo in cui lo farebbe un class
o struct
.
Invece esiste una classe stub denominata SZArrayHelper
che fornisce queste interfacce in fase di esecuzione per matrici a dimensione zero basate su zero. Il commento sul .NET Core Version è informativo:
//----------------------------------------------------------------------------------------
// ! READ THIS BEFORE YOU WORK ON THIS CLASS.
//
// The methods on this class must be written VERY carefully to avoid introducing security holes.
// That's because they are invoked with special "this"! The "this" object
// for all of these methods are not SZArrayHelper objects. Rather, they are of type U[]
// where U[] is castable to T[]. No actual SZArrayHelper object is ever instantiated. Thus, you will
// see a lot of expressions that cast "this" "T[]".
//
// This class is needed to allow an SZ array of type T[] to expose IList<T>,
// IList<T.BaseType>, etc., etc. all the way up to IList<Object>. When the following call is
// made:
//
// ((IList<T>) (new U[n])).SomeIListMethod()
//
// the interface stub dispatcher treats this as a special case, loads up SZArrayHelper,
// finds the corresponding generic method (matched simply by method name), instantiates
// it for type <T> and executes it.
//
// The "T" will reflect the interface used to invoke the method. The actual runtime "this" will be
// array that is castable to "T[]" (i.e. for primitivs and valuetypes, it will be exactly
// "T[]" - for orefs, it may be a "U[]" where U derives from T.)
//----------------------------------------------------------------------------------------
E questo è ciò che accade. Se provi a trasmettere fsArray
a IList<Stream>
, ottieni questa classe che effettua le chiamate per te. Se chiami GetInterfaces()
ottieni un codice stub simile fornendo solo quelli relativi al tipo di array. In entrambi i casi fsArray
fa implementare tutte le interfacce citate nel libro che citate, ma non lo fa allo stesso modo di un can. class
o struct
.
(consideri per analogia come un int
può essere sia quattro byte del valore di 32 bit e un oggetto "pieno" con le implementazioni di interfaccia, metodo override, etc.)
Così il libro è corretto, ma non ti manca nulla, perché alcune delle cose che ci aspettiamo che accadano quando un tipo implementa un'interfaccia non lo fanno.
Inoltre, penso che sia senza significato. Perché gli array supportano la co-varianza.
La co-varianza di supporto non significa che implementeranno una determinata interfaccia, o viceversa. Soprattutto perché la covarianza degli array (probabilmente interrotta) è molto diversa da quella delle interfacce e la precede, e infatti gli array implementano interfacce generiche anche prima della covarianza dell'interfaccia.
Tuttavia, che è stato deciso che FileStream[]
dovrebbe anzi implementare Stream[]
non si riferiscono agli array di essere covariante (la decisione sarebbe stato altrettanto stranamente sbagliato in altro modo), ma ha bisogno l'aiuto supplementare che SZArrayHelper
fornisce, invece di essere implicato automaticamente esso.
Si ha 'System.Collections.Generic.IList'1 [System.IO.FileStream]' –
@NikhilAgrawal 'IList' è nel testo del libro; il testo del libro prosegue affermando che "le interfacce per i tipi di base ..."IEnumerable " dovrebbe anche essere presente, che a quanto pare non sono –
AakashM
Gli odori non corretti. Invia errata, whydoncha https://www.microsoftpressstore.com/contact-us/errata – Will