What is the difference between new Object() and new Object{} in expressions in C#
I have the following code snippet:
Expression<Func<TSource, TDest>> expression = model => new TDest{};
// Result: {model => new TestModel(){}}
ReSharper refactors this snippet with RedundantEmptyObjectOrCollectionInitializer
setting:
Expression<Func<TSource, TDest>> expression2 = model => new TDest();
// Result: {model => new TestModel()}
After that, my code doesn't work. What influence do the curly braces have on initializing?
I found What is the Difference Between new object()
and new {}
in C#? on Stack Overflow, but both instances look equal.
expression.GetType().ToString()
is equal to
expression2.GetType().ToString()
What is the difference between these initializations in expression trees?:
var a = model => new TDest{};
var b = model => new TDest();
Solution 1:
In regular raw C# the answer would be "nothing". However, when you involve expression trees, there is a difference; as can be seen here
using System;
using System.Linq.Expressions;
public class C<TSource, TDest> where TDest : new() {
public Expression<Func<TSource, TDest>> Foo() => model => new TDest();
public Expression<Func<TSource, TDest>> Bar() => model => new TDest {};
}
compiles as:
public Expression<Func<TSource, TDest>> Foo()
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(TSource), "model");
Expression arg_2E_0 = Expression.New(typeof(TDest));
ParameterExpression[] expr_2A = new ParameterExpression[1];
expr_2A[0] = parameterExpression;
return Expression.Lambda<Func<TSource, TDest>>(arg_2E_0, expr_2A);
}
public Expression<Func<TSource, TDest>> Bar()
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(TSource), "model");
Expression arg_38_0 = Expression.MemberInit(Expression.New(typeof(TDest)), Array.Empty<MemberBinding>());
ParameterExpression[] expr_34 = new ParameterExpression[1];
expr_34[0] = parameterExpression;
return Expression.Lambda<Func<TSource, TDest>>(arg_38_0, expr_34);
}
So one of them involves an Expression.MemberInit
(with an empty set of MemberBinding
elements) in addition to Expression.New
. This can upset any LINQ provider (or any similar expression-tree analysis) that doesn't expect it.
Solution 2:
ReSharper is giving you a better suggestion in how to instantiate the TDest
class.
In theory, there isn't any difference as both new TDest ()
and new TDest {}
will provide you with an instance of TDest
.
However, when you use the initialization expression, it's because you want to set values of public properties or fields in TDest
.
class TDest
{
public string MyProperty { get; set; }
}
So you could initialize the TDest
class setting a value to MyProperty
. E.g.:
// Sample 1
new TDest { MyProperty = "This is the value of my property" };
// Sample 2
new TDest() { MyProperty = "This is the value of my property" };
In your case, your class has a parameterless constructor, so both, the punctuators {, }
or operators ()
would be fine.
For simple scenarios where you have a parameterless constructor, you can use only the TDest()
short form.
But if you had for example the below class.
class TDest
{
readonly ISomeInterface _someService;
public string MyProperty { get; set; }
public TDest(ISomeInterface someService)
{
_someService = someService;
}
}
And you wanted to initialize MyProperty
with something rather than its default initialization value (null, reference types), you could use the full object initialization. E.g.:
// Sample 3
new TDest(new MySomeServiceImplementation()) { MyProperty = "This is the value of my property" };
Hopefully it helps!
To have a better idea, go and have a look at C# Object Initializers.