9
if ( (new Func</*out*/ string, bool>( (/*out*/ string uname) => ....

more details : that is a part of login function and I just want that my lambda function to changes login-name user with a out parameter and said me that user logined with it's bool return.

I really understand that I can return the Tuple and then get my string value but I want exactly out parameter for some personal clarity. I better return only string with null if user is not login, just want to know if I can use out parameters inside lambda functions.

And I really get that the code with expressions on the statement places is not so clean But none said me if that is really bad for compiler.

cnd
  • 32,616
  • 62
  • 183
  • 313
  • Note, as such lambda expressions can have `ref/out` parameters. For e.g. this works: `delegate bool Logger(out string name); Logger f = (out string bar) => { bar = ""; //assign return ... };` ..Just that with `Action/Func` you cant do it. You need your own delegate. – nawfal Dec 22 '13 at 03:00

3 Answers3

6

Lambda expressions won't work, but for delegates you should be fine using a statement body:

bool outval = false; // definite assignment
Func<bool> func = () => {
    return SomeMethod(out foo);
};
bool returned = func();
// check both outval and returned

For delegates... You will need to define your own:

public delegate bool MyType(out string value);
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • So... I really don't wanted to use delegates here but I even didn't knew if they can works fine here. – cnd Apr 04 '11 at 14:16
  • 1
    No, you *do* want delegates here, just probably not lambda expressions. – Adam Rackis Apr 04 '11 at 14:19
  • Ok , Yes, I do :) if ((new ChUname((out string uname) => ... works well. – cnd Apr 04 '11 at 14:23
  • 1
    that's still a lambda. You can't have (out string usname) => ... Forget about lambdas and just read about basic delegate usage. – Adam Rackis Apr 04 '11 at 14:26
  • But it works just fine, ChUname is my delegate it can changes my user's name. – cnd Apr 05 '11 at 05:08
  • @AdamRackis Why yes, you _can_ have `(out string usname) => ...`, you just have to have a delegate type whose signature matches. (None of the generic `Func` and `Action` types in the framework have `out` parameters, so they don't match.) For example with `MyType` as above, you can say `MyType f = (out string u) => { u = "assigned"; return true; };`. When `out` or `ref` is applied to some of the parameters, the parameter types (like here `string`) must be present. Then this variable `f` is used as exprected: `string uname; bool result = f(out uname);`. – Jeppe Stig Nielsen Feb 26 '13 at 19:53
  • @AdamRackis So you can assign an `(out string usname) => ...` expression to a delegate variable of type `MyType`. What you cannot do is assign to an expression tree, like a variable of type `Expression`. – Jeppe Stig Nielsen Feb 26 '13 at 19:57
2

You cannot use out parameters with a lambda expression. See this Stack Overflow question.

Pang
  • 9,564
  • 146
  • 81
  • 122
Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
  • 1
    A little confusing. You can have a lambda like `(int i, out int j) => ...`, with the `out` keyword in it, and that lamda can be assigned to a variable of delegate type. It can't be assigned to an expression tree, though. The question you are referring, talks about capturing an `out` parameter of a regular method inside a lambda. That's like `public static bool UsualMethod(out int i) { /* body of normal method */ Action f = () => { Console.WriteLine(i); }; ... ... }`. ***This*** is illegal. The lambda tries to capture an `out` parameter of the containing method. – Jeppe Stig Nielsen Feb 26 '13 at 20:04
2

While you can't use the out keyword I did find a solution that lets you basically achieve C++ style memory pointers in .NET. I found this class due to the very reason you opened this SO question not being able to use an out parameter where I wanted it.

public class Ptr<T>
{
    Func<T> getter;
    Action<T> setter;

    public Ptr(Func<T> g, Action<T> s)
    {
        getter = g;
        setter = s;
    }

    public T Deref
    {
        get { return getter(); }
        set { setter(value); }
    }
}

Usage example

private IDocumentSession _session = DocumentStore.OpenSession()

var ptr = new Ptr<IDocumentSession>(
                () => _session, 
                newValue => _session = newValue))

session.Deref.SaveChanges();
session.Deref = DocumentStore.OpenSession();

I use this in a batch program that allows batch operations to control session flushing with RavenDB when I need fine grained session control while also leaving an ambient session context. Word of warning I have no idea what implications this type of code would have in a long running production app since I'm not sure if this would confuse the GC and cause memory to never be reclaimed.

Chris Marisic
  • 32,487
  • 24
  • 164
  • 258