13

Within C# is it possible to create a new function on the fly to define a variable?

I know that

string getResult() {
    if (a)
        return "a";
    return "b";
}
String result = getResult();

is possible, but I'm looking for something like

String result = new string getResult() {
    if (a)
        return "a";
    return "b";
}

Is this possible? If so, would someone demonstrate?

EDIT It is possible

Edit: Final - Solution

This is the end result of what I barbarically hacked together

Func<string> getResult = () =>
{
    switch (SC.Status)
    {
        case ServiceControllerStatus.Running:
            return "Running";
        case ServiceControllerStatus.Stopped:
            return "Stopped";
        case ServiceControllerStatus.Paused:
            return "Paused";
        case ServiceControllerStatus.StopPending:
            return "Stopping";
        case ServiceControllerStatus.StartPending:
            return "Starting";
        default:
            return "Status Changing";
    }
};

TrayIcon.Text = "Service Status - " + getResult();
Slushba132
  • 423
  • 2
  • 5
  • 20

5 Answers5

14

One way to define such a function:

Func<bool, string> getResult = ( a ) => {
    if (a)
        return "a";
    return "b";
}

You can then invoke: string foo = getResult( true );. As a delegate, it can be stored/passed and invoked when needed.

Example:

string Foo( Func<bool, string> resultGetter ){
    return resultGetter( false );
}

You can also close around variables within scope:

bool a = true;

Func<string> getResult = () => {
    if (a)
        return "a";
    return "b";
}

string result = getResult();
Community
  • 1
  • 1
Tim M.
  • 53,671
  • 14
  • 120
  • 163
  • (If I understand the asker's intent...) I'd recommend against this, since it's not what `Func`s are typically used for, and would be confusing to future readers of your code (yourself included) that are more familiar with normal `Func` usage patterns. Unless it's really an instance where a `Func` or `Action` would make more sense, either inline the code, or make it a separate method. – Tim S. Aug 26 '12 at 01:40
  • I would have to disagree. While I don't know what the OP's needs are and this is a contrived example, the ability to define and repeatedly/conditionally/eventually execute a delegate is both powerful and common. But that's just me. – Tim M. Aug 26 '12 at 01:53
  • This wouldn't really work for me as Tim S. stated. I'd rather just define it in a separate method, if I were to use this route. My only real purpose in doing this was to define it lazy style all in one line like Actionscript, or what I believe is also possible in Javo. Upon realizing it might be harder than I initially intend I was curious how it could be implemented, if it actually could be implemented. – Slushba132 Aug 26 '12 at 01:54
  • You can define a delegate in one line but it's probably not the right fit if that's the only motivation for it. – Tim M. Aug 26 '12 at 01:57
  • The initial method mentioned would have worked, had I wanted to pass the ServiceController (the object my switch is built around in context) with each call to getResult. "getResult(ServiceController);" would have worked, but I didn't want that and looking at that part of your answer threw me off. I see now where you said you can close around variables within scope. This is actually exactly what I was looking for. Sorry for not noticing sooner. – Slushba132 Aug 26 '12 at 02:16
  • This is lambda, not delegate though. – liang May 05 '14 at 02:07
  • @liang - `Func<>` is a delegate, and the example shows a variable of a delegate type having a lambda assigned to it. I like this explanation: http://stackoverflow.com/a/74414/453277 – Tim M. May 05 '14 at 02:27
2

You want to use the inline if statement.

string result = a ? "a" : "b";
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • I feel like this would work, except I'm actually trying to implement a switch. I simplified it to an if statement in my code for the sake of trying to be understood. Is there perhaps an inline switch statement? – Slushba132 Aug 26 '12 at 01:48
  • 1
    you could do it with a `Dictionary`. – Daniel A. White Aug 26 '12 at 01:52
  • A `Dictionary` incurs a lot more overhead than a simple switch statement (relatively speaking). You generally should try to avoid using Dictionaries for logic known at compile time. – MgSam Aug 26 '12 at 03:30
2

If you really want inline you can make an extension method for type String:

static class StringExtensions {
    public static string ExecuteFunc(
            this string str, 
            Func<string, string> func
        ) {
        return func(str);
    }
}

And then, when you want to use it, you do so like so:

string str = "foo";

string result = str.ExecuteFunc( s => {
        switch(s){
            case "a":
                return "A";
            default:
                return "B";
        }
    }
);
James
  • 2,445
  • 2
  • 25
  • 35
  • +1 for using extension. Although it doesn't really pass function around. It can't be assigned once, but have to be assigned whenever invoked. – liang May 05 '14 at 02:06
0

Not sure what the scope of the variable a is in your example, but assuming that it is accessible within the scope (as it is in your example):

Func<string> getResult = () =>
{
    return a ? "a" : "b";
}
Slushba132
  • 423
  • 2
  • 5
  • 20
Zaid Masud
  • 13,225
  • 9
  • 67
  • 88
  • 1
    `Action`s don't return anything; did you mean `Func`? Anyway, I think `var` would probably work... – Ry- Aug 26 '12 at 01:43
  • @minitech, `var` doesn't work with lambdas. There's not enough context for the compiler to know what to make of it. (the compiler error is "Cannot assign lambda expression to an implicitly-typed local variable") – Tim S. Aug 26 '12 at 01:45
  • @TimS.: You'd think it could intelligently determine the return type. Oh well. – Ry- Aug 26 '12 at 01:47
  • @minitech or you can get ReSharper to extract the function as a variable and intelligently determine the return type :) – Zaid Masud Aug 26 '12 at 01:50
  • 1
    @minitech the root reason (or so I infer) is that `Func` and `Action` don't have any special status in the C# compiler - they're just delegates. If you had a delegate defined that had the same signature, how could it know which you'd like it to be? E.g. even among very common built-in delegates, `Action` and `EventHandler` are the same. – Tim S. Aug 26 '12 at 01:54
  • Using this I was able to create what I was looking for (A variable defined by a new function upon instantiation, all in the nice laziness of a "single line style"). It may not be as pretty as ActionScript, but it serves it's purpose. Thank you. – Slushba132 Aug 26 '12 at 02:00
  • @BustyLoli-Chan if an answer is useful to you please upvote it. – Zaid Masud Oct 23 '12 at 18:43
0

Based on the solution you posted, here is a better way to do this.

Change your ServiceControllerStatus enum to add [Description] attributes:

public enum ServiceControllerStatus
{
    [Description("Running")]
    Running,
    // ... others
}

Add the following extension method in a new static class:

public static string ToDescription(this Enum value)
{
    var attributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
    return attributes.Length > 0 ? attributes[0].Description : value.ToString();
}

Now you can simply write:

TrayIcon.Text = "Service Status - " SC.Status.ToDescription();
Zaid Masud
  • 13,225
  • 9
  • 67
  • 88