2012-01-20 24 views
15

En Java, es posible ampliar una interfaz con una clase anónima que puede implementar sobre la marcha. Ejemplo:C# implementación anónima de la interfaz (o clase abstracta)

Runnable myRunnable = new Runnable() 
{ 
    @Override 
    public void run() { /**/ } 
} 

(Más en: http://www.techartifact.com/blogs/2009/08/anonymous-classes-in-java.html#ixzz1k07mVIeO)

Es esto posible en C#? Si no, ¿cuáles son las alternativas viables sin tener que depender de la implementación de una plétora de subclases?

Respuesta

14

No, no se puede hacer eso en C# - pero típicamente el enfoque de diseño alternativo es utilizar un delegado en su lugar. En el ejemplo que has dado, Runnable se suele representar mediante ThreadStart, y se puede utilizar un método o lambda expresión anónima:

ThreadStart start =() => 
{ 
    // Do stuff here 
}; 

O si sólo hay un método para ejecutar, con la firma correcta, puede utilizar una conversión de grupo método:

ThreadStart start = MethodToRunInThread; 

o en la convocatoria Thread constructor:

Thread t = new Thread(MethodToRunInThread); 
t.Start(); 

Si realmente necesita implementar una interfaz, tendrá que implementarlo realmente (posiblemente en una clase anidada privada). Sin embargo, según mi experiencia, eso no aparece muy a menudo en C#. Normalmente, las interfaces de C# son del tipo que naturalmente exigiría una implementación "real" de todos modos, incluso en Java.

+1

Esta es una característica que extraño de vez en cuando, especialmente porque mis interfaces son a menudo estrechas (interfaces de función) y se adhieren al principio de segregación de interfaz. Sería conveniente cuando pudiera registrar un delegado en mi configuración DI, mientras que el resto de la aplicación aún podría depender de esa interfaz (en lugar de 'Func '), sin tener que crear algún tipo de clase proxy que envuelva a ese delegado e implementar esa interfaz. – Steven

6

Como Jon señaló que esto no es posible en C#.

Un patrón alternativo en C# es usar una combinación de una fábrica y un delegado para permitir implementaciones sobre la marcha de una interfaz. Esencialmente, la fábrica toma un delegado para cada método de la interfaz y los utiliza como la implementación de respaldo. Por ejemplo, aquí hay una versión para IComparable<T>.

public static class ComparableFactory { 
    private sealed ComparableImpl<T> : IComparable<T> { 
    internal Func<T, T, int> _compareFunc; 
    public int Compare(T left, T right) { 
     return _compareFunc(left, right); 
    } 
    } 
    public IComparable<T> Create<T>(Func<T, T, int> compareFunc) { 
    return new ComparableImpl<T>() { _compareFunc = compareFunc }; 
    } 
} 

... 

IComparable<Person> impl = CompareableFactory.Create<Person>(
    (left, right) => left.Age.CompareTo(right.Age)); 
+0

¡Muy bueno, +1! Pero como una buena práctica, es mejor rodar la clase nombrada ... – nawfal

Cuestiones relacionadas