2010-03-06 7 views
1

J'utilise le code suivant pour passer une propriété à une expression lambda.Comment créer une méthode qui accepte une expression lambda comme argument?

namespace FuncTest 
{ 
    class Test 
    { 
     public string Name { get; set; } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Test t = new Test(); 
      t.Name = "My Test"; 
      PrintPropValue(t => t.Name); 

     } 

     private static void PrintPropValue(Func<string> func) 
     { 
      Console.WriteLine(func.Invoke()); 
     } 

    } 
} 

Cela ne compile pas. Je veux juste que la fonction puisse prendre la propriété et être capable d'évaluer.

+0

Quelle est l'erreur de compilation? –

+0

Pourquoi ne pas se contenter d'un 'PrintPropValue (string prop)' void alors au lieu de jongler avec lambdas? Voulez-vous avoir des expressions qui prennent une instance et retournent une propriété? –

+0

@amdras: J'essaie juste d'apprendre les lamdas. – Amitabh

Répondre

8

A Func<string> n'a pas de paramètres - mais votre expression lambda fait.

On ne sait pas si vous vraiment voulez un Func<Test, string> - dans ce cas, vous devrez passer dans une instance de Test lorsque vous invoquez le délégué - ou si vous voulez un Func<string> qui capture une instance particulière de test. Pour le dernier:

using System; 

class Test 
{ 
    public string Name { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Test t = new Test(); 
     t.Name = "My Test"; 
     // Note: parameterless lambda expression 
     PrintPropValue(() => t.Name); 

     // Demonstration that the reference to t has been captured, 
     // not just the name: 

     Func<string> lambda =() => t.Name; 
     PrintPropValue(lambda); 
     t.Name = "Changed"; 
     PrintPropValue(lambda); 
    } 

    private static void PrintPropValue(Func<string> func) 
    { 
     Console.WriteLine(func.Invoke()); 
    } 
} 
2
class Program 
{ 
    static void Main(string[] args) 
    { 
     Test t = new Test(); 
     t.Name = "My Test"; 

     //Use a lambda with a free variable 
     Func<Test, string> lambda = x => x.Name; 
     PrintPropValue(t, lambda); 

     //Close the lambda over its free variable. 
     //It will refer to the t 
     //captured from the current scope from now on 
     //Note: 'lambda' is unchanged, it still can be used 
     //with any 'Test' instance. We just create a (new) 
     //closure using the 'lambda'. 
     Func<string> closure =() => lambda(t); 
     PrintPropValue(closure); 

     //This will still print 'My Test', 
     //despite the fact that t in that scope 
     //refers to another variable. 
     AnotherT(closure); 

     t.Name = "All your " + t.Name + " captured and are belong to us."; 
     //This will now print 'All your My Test captured and are belong to us.' 
     AnotherT(closure); 

    } 

    private static void AnotherT(Func<string> closure) 
    { 
     Test t = new Test(); 
     t.Name = "My Another Test"; 

     PrintPropValue(closure); 

    } 

    private static void PrintPropValue<T>(T instance, Func<T, string> func) 
    { 
     Console.WriteLine(func(instance)); 
    } 

    private static void PrintPropValue(Func<string> func) 
    { 
     Console.WriteLine(func()); 
    } 

} 
Questions connexes