What is the difference between new Object() and new Object{} in expressions in C#

C#.NetResharper

C# Problem Overview


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();

C# Solutions


Solution 1 - C#

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 - C#

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncSteusloffView Question on Stackoverflow
Solution 1 - C#Marc GravellView Answer on Stackoverflow
Solution 2 - C#AlexzView Answer on Stackoverflow