315 votos

Método de paso como parámetro usando C#

Tengo varios métodos con la misma firma (parámetros y valores devueltos) pero diferentes nombres y las partes internas de los métodos son diferentes. Quiero pasar el nombre del método que se ejecutará a otro método que se invocará el método pasado.

public int Method1(string)
{
    ... do something
    return myInt;
}

public int Method2(string)
{
    ... do something different
    return myInt;
}

public bool RunTheMethod([Method Name passed in here] myMethodName)
{
    ... do stuff
    int i = myMethodName("My String");
    ... do more stuff
    return true;
}

public bool Test()
{
    return RunTheMethod(Method1);
}

Este código no funciona, pero esto es lo que estoy tratando de hacer. Lo que no entiendo es cómo escribir el código de RunTheMethod ya que tengo que definir el parámetro.

386voto

Egil Hansen Puntos 3999

Puede utilizar al delegado Func en .net 3.5 como parámetro en el método RunTheMethod. El delegado Func le permite especificar un método que toma un número de parámetros de un tipo específico y devuelve un único argumento de un tipo específico. Aquí hay un ejemplo que debería funcionar:

public class Class1
{
    public int Method1(string input)
    {
        //... do something
        return 0;
    }

    public int Method2(string input)
    {
        //... do something different
        return 1;
    }

    public bool RunTheMethod(Func<string, int> myMethodName)
    {
        //... do stuff
        int i = myMethodName("My String");
        //... do more stuff
        return true;
    }

    public bool Test()
    {
        return RunTheMethod(Method1);
    }
}

216voto

Jon Skeet Puntos 692016

Usted necesita usar un delegado. En este caso, todos los métodos tomar un string parámetro y devuelve un int - esto es, la mayoría, simplemente, representado por el Func<string, int> delegado1. Por lo tanto el código puede convertirse en corregir con un simple cambio como este:

public bool RunTheMethod(Func<string, int> myMethodName)
{
    // ... do stuff
    int i = myMethodName("My String");
    // ... do more stuff
    return true;
}

Los delegados tienen mucho más poder que este, sin duda. Por ejemplo, en C# se puede crear un delegado de una expresión lambda, por lo que podría invocar el método de esta manera:

RunTheMethod(x => x.Length);

Que va a crear una función anónima como este:

private static int <>_HiddenMethod_<>(string x)
{
    return x.Length;
}

y, a continuación, pasar delegado a la RunTheMethod método.

Puede utilizar los delegados para el caso de las suscripciones, la ejecución asíncrona, las devoluciones de llamada - todo tipo de cosas. Bien vale la pena leer sobre ellos, especialmente si usted desea usar LINQ. Tengo un artículo que es principalmente acerca de las diferencias entre delegados y eventos, pero es posible que encuentre útil de todos modos.


1 Este se basa solamente en la genérica Func<T, TResult> tipo de delegado en el marco; fácilmente podría declarar tu propio:

public delegate int MyDelegateType(string value)

y, a continuación, hacer que el parámetro de tipo MyDelegateType lugar.

49voto

Zain Ali Puntos 3813

Usted puede también intentar a delegado de acción!

 public static int Method1(string mystring)
       {
           return 1;
       }

        public static int Method2(string mystring)
     {
       return 2;
     }

 public bool RunTheMethod(Action myMethodName)
        {
            myMethodName();
            return true;
        }

Y entonces llama a su método usando

RunTheMethod(() => Method1("MyString1"));

O

public static object InvokeMethod(Delegate method, params object[] args)
         {
             return method.DynamicInvoke(args);
         }

Entonces simplemente llamar método

 Console.WriteLine(InvokeMethod(new Func<string,int>(Method1), "MyString1"));

Console.WriteLine(InvokeMethod(new Func<string, int>(Method2), "MyString2"));

10voto

Bruno Reis Puntos 16132

Usted debe usar un Func<string, int> delegado, que representa una toma de función un string como argumento y devolver un int :

public bool RunTheMethod(Func<string, int> myMethod) {
    // do stuff
    myMethod.Invoke("My String");
    // do stuff
    return true;
}

Entonces usarlo:

public bool Test() {
    return RunTheMethod(Method1);
}

6voto

MadcapLaugher Puntos 510

Si quieres que la capacidad de cambiar de método que se llama en tiempo de ejecución yo recomendaría usar un delegado: http://www.codeproject.com/KB/cs/delegates_step1.aspx

Nos permite crear un objeto para almacenar el método a llamar y a sus otros métodos puede pasar cuando sea necesario.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X