Expression-Bodied Function Members Efficiency and Performance in C# 6.0

Expression-bodied function members efficiency and performance in C# 6.0

In a new C# 6.0 we can define methods and properties using lambda expressions.

No, you can't. You can define method and property bodies using syntax which looks like a lambda expression, in that it uses the token =>.

However, importantly this does not mean that there's a delegate type involved. (Whereas a lambda expression is only permitted in a context where it's converted to an expression tree or delegate type.)

This is purely syntactic sugar. Your two example code snippets will compile to the exact same IL. It's just a different way of representing the body of a property getter or method.

Is the body expression more efficient than the simple return of a member variable?

The second code snippet is a pure syntactic sugar added in C# 6.0. That means it compiles to the exact same IL code as the first snippet and there is absolutely no difference in performance (or otherwise) at runtime. Use whatever style you like.

using Expression-bodied members improve some performance?

Very often it is used just to write shorter (thus writting code faster?) and more readable code.

But trying to force => whenever you can may have negative effect on readability of yours code.

Why use expression-bodied properties for primitive values?

There are quite a few differences between those two lines of code:

  1. The first one is a property, the second is a field. For example, you cannot ref the first Foo.
  2. The property gets evaluated and returns a new object every time, even if the object is the same string literal. The variable is evaluated once and when used it's just loaded. (Note that a better way to write #1 is public string Foo { get; } = "Bar"; which would also be initialized once and then return the same value).
  3. The first one is read-only (it's a getter only), while the second one is a mutable variable, you can write into it. A closer equivalent would be public readonly string Foo = "Bar"; or even better public static readonly string Foo = "Bar";

Expression-bodied function members in previous C#

Not really, the easiest you can do is:

public string FullAddress
{
get
{
return string.Format("{0} {1} {2}, {3}, {4}, {5}",
Title, FirstName, LastName, Street, City, ZIP);
}
}

You will unfortunately miss both the expression body and string interpolation syntax.

Expression Bodied method performance (return new instance via factory method vs cached reference)

private static List<Guid> GetList() => new()
{
new Guid("f93b8c93-3084-4087-8727-dad436fe5b76"),
new Guid("6894046e-1deb-4128-b639-aa472f7f95d3")
// many more
};

This will create a new list each time you call the GetList function. i.e, making changes to this list after calling the GetList will apply just to this instance and will not apply to other instances who called the GetList function.

private static List<Guid> GetList()
{
return CacheList;
}

The GetList method in this example will return the same instance for everyone calling this function. i.e, modifying this list will apply the changes to whoever called this function and asked for that particular instance.

In terms of performance, there is no difference between regular function to expression body. It's a pure syntactic sugar added in C# 6.0. That means it compiles to the same IL code and there is absolutely no difference in performance.

Expression-bodied members strange case

That's not an expression-bodied member per se. That's a lambda expression. Lambdas were added to C# 3; the expression-bodied member feature was added much later and was designed to look like lambda syntax.

You can think of

Assert.Throws<DivideByZeroException>(() => calculator.Divide(5, 0));

as being like

class Whatever 
{
static double SomeFunction() => calculator.Divide(5, 0);
...
... later
Func<double> f = SomeFunction;
Assert.Throws<DivideByZeroException>(f);

Does that make it more clear?

In short: Assert.Throws takes a function, it calls the function, and it verifies that the function throws an exception. It is crucially important that it takes a function that can be called. You can't just say

Assert.Throws<Whatever>(calculator.Divide(5, 0))

because that throws before Throws is called!

Expression-Bodied Function combined with Auto Properties results in problems

Let's go though the options you gave one by one and look at what each does:

  1. private static string _bootstrapBundle;
    public static string BootstrapBundle
    {
    get
    {
    return _bootstrapBundle;
    }
    }

    I'm assuming that I don't have to explain what this does. But note that if you try to assign to BootstrapBundle, it will fail at compile time, since there is no setter. But you can work around that by assigning directly to the field.

  2. private static string _bootstrapBundle;
    public static string BootstrapBundle => _bootstrapBundle;

    This is exactly the same as #1, only with more succinct syntax.

  3. public static string BootstrapBundle { get; private set; }

    Here we have an auto-property, that is a property with hidden (unspeakable) backing field. It compiles to:

    private static string <BootstrapBundle>k__BackingField;
    public static string BootstrapBundle
    {
    get
    {
    return <BootstrapBundle>k__BackingField;
    }
    private set
    {
    <BootstrapBundle>k__BackingField = value;
    }
    }

    This means that setting the property now works and getting it after setting will give you the new value.

  4. private static string _bootstrapBundle;
    public static string BootstrapBundle { get; private set; } = _bootstrapBundle;

    This is the same as #3, except that the hidden backing field is initialized to the value you gave:

    private static string _bootstrapBundle;
    private static string <BootstrapBundle>k__BackingField = _bootstrapBundle;
    public static string BootstrapBundle
    {
    get
    {
    return <BootstrapBundle>k__BackingField;
    }
    private set
    {
    <BootstrapBundle>k__BackingField = value;
    }
    }

    What this means is that there are now two fields: one hidden and one visible. The hidden field will initially be set to the value of the visible field (which is null), but after that, the two fields won't affect each other.

    This means that if you set the property, and then get the property, you will get the updated value. But if you read the visible field, its value won't be updated. And vice versa: if you update the field, the value of the property won't change.



Related Topics



Leave a reply



Submit