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:
- The first one is a property, the second is a field. For example, you cannot
ref
the firstFoo
. - 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). - 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 betterpublic 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:
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.private static string _bootstrapBundle;
public static string BootstrapBundle => _bootstrapBundle;This is exactly the same as #1, only with more succinct syntax.
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.
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
Can You Prevent Your ASP.NET Application from Shutting Down
C# 8 Switch Expression with Multiple Cases with Same Result
How to Serialize/Deserialize Simple Classes to Xml and Back
How to Create a Sequence of Integers in C#
C# Waiting for Multiple Threads to Finish
Why Does This Simple .Net Console App Have So Many Threads
How to Check for Nulls in a Deep Lambda Expression
What Do the "+N" Values Mean at the End of a Method Name in a Stack Trace
JSON.Net Custom Serialization with JSONconverter - How to Get the "Default" Behavior
How to Enable Nullable Reference Types Feature of C# 8.0 for the Whole Project
ASP.NET MVC Routing - Add .HTML Extension to Routes
Launching Process in C# Without Distracting Console Window
How to Convert String to Integer in C#
Circular Reference Causing Stack Overflow with Automapper