17

I have a method with the following signature:

private PropertyInfo getPropertyForDBField(string dbField, out string prettyName)

In it, I find the associated value prettyName based on the given dbField. I then want to find all properties, if any, that have the name prettyName, so I'm trying to do the following:

IEnumerable<PropertyInfo> matchingProperties =
    getLocalProperties().Where(prop =>
        prop.Name.Equals(prettyName)
    );

However, this gives the following error:

Cannot use ref or out parameter 'prettyName' inside an anonymous method, lambda expression, or query expression

By the point in the method where I'm trying to use prettyName in the Where lambda parameter, prettyName is definitely initialized. I return if prettyName cannot be initialized to a valid value. Is there some trick I could do here to let me use prettyName in the lambda expression?

Edit: I'm using .NET 3.5 if it matters.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Sarah Vessels
  • 30,930
  • 33
  • 155
  • 222
  • 1
    What about storing the value you would put to prettyName into a different variable so that you can do `prettyName = someval;` then use `someval` in your anon function? – myermian Oct 28 '10 at 18:05
  • As the accepted answer shows, what you wrote in the title is not what you're trying to do, please change it. – v01pe May 28 '20 at 08:46

2 Answers2

30

Just to clarify. It's possible to use ref/out arguments from a called method in a lambda.

You can also use a ref or out if you specify type of the parameter. Which means sending prettyName as a parameter to the lambda.

(prop, ref string prettyName) => prop.Name.Equals(prettyName);

Where clause takes in only one argument, which is the property element in the list. This is what prevents you from adding an argument to the lambda.

Didn't want to leave people the false impression that you cannot use these arguments in a lambda. You just can't use them by capture.

Lee Louviere
  • 5,162
  • 30
  • 54
  • Lee, for some reason I can't get this to work. The code I am using is IEnumerable matchingProperties = getLocalProperties().Where((prop, ref string prettyName) => prop.Name.Equals(prettyName) ); ...but it gives an error on the "ref" ("A local variable named 'prettyName' cannot be declared in this scope because it would give a different meaning to 'prettyName' which is already used in a parent or current scope. – Francine DeGrood Taylor Jun 19 '14 at 18:26
  • Or were you saying that you still have to reassign prettyName to a different string variable, but that you could then pass it in by ref or out? – Francine DeGrood Taylor Jun 19 '14 at 18:31
  • Yes, you have to name it differently. When I wrote this answer, i tested with some sample code that didn't give meaningful names. so i probably named the two differently. – Lee Louviere Jun 20 '14 at 14:44
  • however, i didn't test if this could cause the variable to magically change at some point on you. that's why they have the restriction set in the first place. they want to avoid you causing the variable to magically change later on, because when you pass an arg to a delegate it actually holds a reference to that arg. since the delegate could be called at any time by passing it somewhere else or storing it for future use, your arg will live longer than the method it was declared within. – Lee Louviere Jun 20 '14 at 14:48
20

As the compiler error indicates, it isn't allowed to use out or ref parameters inside lambda expressions.

Why not just use a copy? It's not like the lambda wants to mutate the variable anyway, so I don't see a downside.

string prettyNameCopy = prettyName;
var matchingProperties = getLocalProperties()
                        .Where(prop => prop.Name == prettyNameCopy);

Alternatively, you can use a local throughout (to evaluate the appropriate name etc.), and assign the outparameter prettyName just before returning from the method. This will probably be more readable if there isn't significant branching within the method.

Ani
  • 111,048
  • 26
  • 262
  • 307
  • ...Okay, now I just feel silly. I was looking up how to use a `delegate` or something crazy to do this. Thanks! – Sarah Vessels Oct 28 '10 at 18:06
  • Cheers. `delegate` wouldn't have helped much since the same restriction also applies to anonymous delegates. – Ani Oct 28 '10 at 18:12