una referencia puede propiedad programacion por pase pasar pasaje parámetro parametros metodos indizador funciones con como c# .net methods delegates

referencia - Pase el método como parámetro usando C#



una propiedad o un indizador no se puede pasar como parámetro out o ref (10)

¡También puedes probar Action Delegate!

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 luego llama a tu método usando

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

O

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

Entonces simplemente llama al método

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

Tengo varios métodos, todos con la misma firma (parámetros y valores de retorno), pero diferentes nombres y las partes internas de los métodos son diferentes. Quiero pasar el nombre del método para ejecutar a otro método que invoque 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 RunTheMethod ya que necesito definir el parámetro.


Aquí hay un ejemplo que puede ayudarlo a comprender mejor cómo pasar una función como parámetro.

Supongamos que tiene la página principal y desea abrir una ventana emergente secundaria. En la página principal hay un cuadro de texto que debe rellenarse basándose en el cuadro de texto emergente secundario.

Aquí necesitas crear un delegado.

Parent.cs // declaración de delegados public delegate void FillName (String FirstName);

Ahora cree una función que llenará su cuadro de texto y la función debe asignar delegados

//parameters public void Getname(String ThisName) { txtname.Text=ThisName; }

Ahora, al hacer clic en el botón, necesita abrir una ventana emergente secundaria.

private void button1_Click(object sender, RoutedEventArgs e) { ChildPopUp p = new ChildPopUp (Getname) //pass function name in its constructor p.Show(); }

En el constructor ChildPopUp, debe crear el parámetro de ''tipo de delegado'' de la página principal //

ChildPopUp.cs

public Parent.FillName obj; public PopUp(Parent.FillName objTMP)//parameter as deligate type { obj = objTMP; InitializeComponent(); } private void OKButton_Click(object sender, RoutedEventArgs e) { obj(txtFirstName.Text); // Getname() function will call automatically here this.DialogResult = true; }



Debe usar un delegado Func<string, int> , que representa una función que toma una string como argumento y devuelve un int :

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

Entonces úsalo:

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


Necesitas utilizar un delegado . En este caso, todos sus métodos toman un parámetro de string y devuelven un int . Esto se representa de la manera más simple mediante el delegado Func<string, int> 1 . Por lo tanto, su código puede ser correcto con un cambio tan simple 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 esto, la verdad. Por ejemplo, con C # puede crear un delegado a partir de una expresión lambda , por lo que podría invocar su método de esta manera:

RunTheMethod(x => x.Length);

Eso creará una función anónima como esta:

// The <> in the name make it "unspeakable" - you can''t refer to this method directly // in your own code. private static int <>_HiddenMethod_<>(string x) { return x.Length; }

y luego pase ese delegado al método RunTheMethod .

Puede usar delegados para suscripciones de eventos, ejecución asíncrona, devoluciones de llamada, todo tipo de cosas. Vale la pena leer sobre ellos, especialmente si desea usar LINQ. Tengo un article que trata sobre todo de las diferencias entre delegados y eventos, pero puede encontrarlo útil de todos modos.

1 Esto se basa únicamente en el tipo genérico de delegado Func<T, TResult> en el marco; Usted podría fácilmente declarar su propio:

public delegate int MyDelegateType(string value)

y luego hacer que el parámetro sea de tipo MyDelegateType en MyDelegateType lugar.


Para compartir una solución lo más completa posible, terminaré presentando tres formas diferentes de hacerlo, pero ahora comenzaré desde el principio más básico.

Breve introducción

Todos los idiomas CLR ( Common Language Runtime ) (como C # y Visual Basic) funcionan bajo una máquina virtual llamada CLI ( Common Language Intérprete ) que ejecuta el código en un nivel más alto que los lenguajes nativos como C y C ++ (que se compilan directamente en el código de máquina) . De ello se deduce que los métodos no son ningún tipo de bloque compilado, sino que son solo elementos estructurados que CLR reconoce y utiliza para extraer su cuerpo y reescribirlo a las instrucciones en línea del código de la máquina. Por lo tanto, no puede pensar pasar un método como parámetro, porque un método no produce ningún valor por sí mismo: ¡no es una expresión válida! Así que, vas a tropezar con el concepto de delegado.

¿Qué es un delegado?

Un delegado representa un puntero a un método. Debido a que (como dije anteriormente) un método no es un valor, hay una clase especial en los idiomas de CLR: Delegate . Esa clase envuelve cualquier método y puedes implícitamente lanzar cualquier método para eso.

Mira el siguiente ejemplo de uso:

static void MyMethod() { Console.WriteLine("I was called by the Delegate special class!"); } static void CallAnyMethod(Delegate yourMethod) { yourMethod.DynamicInvoke(new object[] { /*Array of arguments to pass*/ }); } static void Main() { CallAnyMethod(MyMethod); }

Las tres formas:

  • Camino 1
    Utilice la clase especial Delegate directamente como en el ejemplo anterior. El problema de esta solución es que su código se desactivará a medida que pase dinámicamente sus argumentos sin restringirlos a los tipos de aquellos en la declaración del método.

  • Manera 2/3 Además de la clase especial Delegate , el concepto de delegados se extiende a los delegados personalizados, que son declaraciones de métodos precedidos por la palabra clave del delegate y se comportan como un método normal. Están tan controlados y obtendrás un código " perfecto ".

Mira el siguiente ejemplo:

delegate void PrintDelegate(string prompt); static void PrintSomewhere(PrintDelegate print, string prompt) { print(prompt); } static void PrintOnConsole(string prompt) { Console.WriteLine(prompt); } static void PrintOnScreen(string prompt) { MessageBox.Show(prompt); } static void Main() { PrintSomewhere(PrintOnConsole, "Press a key to get a message"); Console.Read(); PrintSomewhere(PrintOnScreen, "Hello world"); }

Una segunda opción de esta manera para no escribir su propio delegado personalizado es usar uno de ellos declarado dentro de las bibliotecas del sistema:

  • Action envuelve un void sin argumentos.
  • Action<T1> envuelve un void con un argumento.
  • Action<T1, T2> envuelve un void con dos argumentos.
  • Y así...
  • Func<TR> ajusta una función con el tipo de retorno TR y sin argumentos.
  • Func<TR, T1> envuelve una función con el tipo de retorno TR y con un argumento.
  • Func<TR, T1, T2> envuelve una función con el tipo de retorno TR y con dos argumentos.
  • Y así...

(Esta última solución es que muchas personas publicaron.)


Puede usar el delegado de funciones en .net 3.5 como el parámetro en su método RunTheMethod. El delegado de funciones le permite especificar un método que toma una serie de parámetros de un tipo específico y devuelve un solo 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); } }


Si bien la respuesta aceptada es absolutamente correcta, me gustaría proporcionar un método adicional.

Terminé aquí después de hacer mi propia búsqueda de una solución a una pregunta similar. Estoy creando un marco impulsado por complementos, y como parte de él quería que las personas pudieran agregar elementos de menú al menú de aplicaciones a una lista genérica sin exponer un objeto de Menu real porque el marco puede implementarse en otras plataformas que no tienen Menu objetos de la interfaz de usuario. Agregar información general sobre el menú es bastante fácil, pero permitir que el desarrollador del complemento tenga la libertad suficiente para crear la devolución de llamada cuando se hace clic en el menú resultó ser una molestia. ¡Hasta que me di cuenta de que estaba intentando reinventar la rueda y los menús normales llaman y activan la devolución de llamada de los eventos!

Así que la solución, tan simple como suena una vez que te das cuenta, me eludió hasta ahora.

Simplemente cree clases separadas para cada uno de sus métodos actuales, heredadas de una base si es necesario, y simplemente agregue un controlador de eventos a cada uno.


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

Te permitirá crear un objeto para almacenar el método para llamar y puedes pasarlo a tus otros métodos cuando sea necesario.


public static T Runner<T>(Func<T> funcToRun) { //Do stuff before running function as normal return funcToRun(); }

Uso:

var ReturnValue = Runner(() => GetUser(99));