En C #, comencé a ver aparecer todos estos métodos mágicos, sin una copia de seguridad de una interfaz. ¿Por qué fue elegido esto?
Dejame explicar.
Anteriormente en C #, si un objeto implementaba la IEnumerableinterfaz, sería iterable automáticamente por un foreachbucle. Eso tiene sentido para mí, ya que está respaldado por una interfaz, y si tuviera que repetir mi propia Iteratorfunción dentro de la clase, podría hacerlo sin preocuparme de que mágicamente significara otra cosa.
Ahora, aparentemente, (no estoy seguro de cuándo), estas interfaces ya no son necesarias. Solo necesita tener las conversiones de nombres correctas.
Otro ejemplo es hacer que cualquier objeto sea aceptable al tener un método llamado exactamente GetAwaiter que tiene algunas propiedades específicas.
¿Por qué no hacer una interfaz como lo hicieron con ellos IEnumerableo INotifyPropertyChangedpara respaldar esta "magia" estáticamente?
Más detalles sobre lo que quiero decir aquí:
http://blog.nem.ec/2014/01/01/magic-methods-c-sharp/
¿Cuáles son los pros y los contras de los métodos mágicos? ¿Existe algún sitio en línea donde pueda encontrar algo sobre por qué se tomaron estas decisiones?

async/await, eso solo funcionará con el código que se escribió después de que .NET 4.5 se extendió lo suficiente como para ser un objetivo viable ... que es básicamente ahora. Pero una traducción puramente sintáctica en llamadas a métodos me permite agregarawaitfuncionalidad a los tipos existentes después del hecho.foreachbucle al principio. Hay que nunca ha sido un requisito para el objeto de implementarIEnumerableparaforeachel trabajo. Ha sido una convención hacerlo.Respuestas:
En general, los "métodos mágicos" se utilizan cuando no es posible crear una interfaz que funcione de la misma manera.
Cuando
foreachse introdujo por primera vez en C # 1.0 (ese comportamiento ciertamente no es nada reciente), tuvo que usar métodos mágicos, porque no había genéricos. Las opciones básicamente fueron:Utilice el no genérico
IEnumerableyIEnumeratorque funcione conobjects, lo que significa tipos de valores de boxeo. Dado que iterar algo como una lista deints debería ser muy rápido y ciertamente no debería crear muchos valores en caja de basura, esta no es una buena opción.Espera genéricos. Esto probablemente significaría retrasar .Net 1.0 (o al menos
foreach) por más de 3 años.Usa métodos mágicos.
Por lo tanto, eligieron la opción n. ° 3 y se quedó con nosotros por razones de compatibilidad con versiones anteriores, aunque desde .Net 2.0, requerirlo
IEnumerable<T>también habría funcionado.Los inicializadores de colección pueden verse diferentes en cada tipo de colección. Compara
List<T>:y
Dictionary<TKey, TValue>:No puede tener una única interfaz que admita solo el primer formulario
List<T>y solo el segundoDictionary<TKey, TValue>.Los métodos LINQ generalmente se implementan como métodos de extensión (de modo que puede haber una sola implementación de, por ejemplo, LINQ to Object para todos los tipos que implementan
IEnumerable<T>), lo que significa que no es posible usar una interfaz.Para
await, ElGetResult()método puede devolver unovoido algún tipoT. Nuevamente, no puede tener una sola interfaz que pueda manejar ambas. Aunqueawaitestá parcialmente basado en la interfaz: el camarero tiene que implementarINotifyCompletiony también puede implementarICriticalNotifyCompletion.fuente
foreachen C # 1.2 (no hay nada en MSDN para C # 1.0) dice que la expresión enforeach"Evalúa a un tipo que implementaIEnumerableo un tipo que declara unGetEnumeratormétodo". Y no estoy seguro de qué quiere decir con eso, unboxing en C # siempre es explícito.foreach(T x in sequence)aplica conversiones explícitas aTlos elementos de la secuencia. Entonces, si la secuencia es simpleIEnumerableyTes un tipo de valor, se desempaquetará sin que se escriba ningún molde explícito en su código. Una de las partes más feas de C #.foreach).