¿Por qué se implementaron los métodos mágicos en C #?

14

En C #, comencé a ver que todos estos métodos mágicos aparecían sin ser respaldados por una interfaz. ¿Por qué eligió esto Anders Hejlsbjerg (o quien esté a cargo del desarrollo de C # en este momento)?

Déjame explicarte.

Anteriormente en C #, si un objeto implementaba la interfaz IEnumerable , sería iterable automáticamente por un bucle foreach . Eso tiene sentido para mí, ya que está respaldado por una interfaz, y si tuviera mi propia función Iterator dentro de la clase que se está repitiendo, podría hacerlo sin preocuparme de que mágicamente significaría 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 se pueda esperar al tener un método llamado exactamente GetAwaiter que tiene algunas propiedades específicas.

¿Por qué no hacer una interfaz como lo hicieron con IEnumerable o INotifyPropertyChanged para respaldar esta "magia" de forma estática?

Más detalles sobre lo que quiero decir aquí:

enlace

¿Cuáles son los pros y los contras de los métodos mágicos? ¿Hay algún lugar en línea donde pueda encontrar algo sobre por qué se tomaron estas decisiones?

    
pregunta Mathias Lykkegaard Lorenzen 13.08.2014 - 22:07

1 respuesta

14

En general, los "métodos mágicos" se usan cuando no es posible crear una interfaz que funcione de la misma manera.

Cuando foreach se introdujo por primera vez en C # 1.0 (ese comportamiento no es nada reciente), tuvo que usar métodos mágicos, porque no había genéricos. Las opciones básicamente fueron:

  1. Utilice los IEnumerable y IEnumerator no genéricos que funcionan con object s, lo que significa tipos de valor de boxeo. Ya que iterar algo como una lista de int s debería ser muy rápido y, desde luego, no debería crear muchos valores en cajas de basura, esta no es una buena opción.

  2. Espere los genéricos. Esto probablemente significaría retrasar .Net 1.0 (o al menos foreach ) por más de 3 años.

  3. Usa métodos mágicos.

Por lo tanto, eligieron la opción # 3 y se quedó con nosotros por razones de compatibilidad con versiones anteriores, aunque desde .Net 2.0, requerir IEnumerable<T> también hubiera funcionado.

Los inicializadores de colección pueden verse diferentes en cada tipo de colección. Compara List<T> :

public void Add(T item)

y Dictionary<TKey, TValue> :

public void Add(TKey key, TValue value)

No puede tener una única interfaz que admita solo la primera forma para List<T> y solo la segunda para Dictionary<TKey, TValue> .

Los métodos LINQ generalmente se implementan como métodos de extensión (de modo que puede haber solo una 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 , el método GetResult() puede devolver void o algún tipo T . Nuevamente, no puedes tener una sola interfaz que pueda manejar ambas. Aunque await está parcialmente basado en la interfaz: el usuario debe implementar INotifyCompletion y también puede implementar ICriticalNotifyCompletion .

    
respondido por el svick 13.08.2014 - 23:42

Lea otras preguntas en las etiquetas