В чем разница между new Object() и new Object{} в выражениях в C#


у меня есть следующий фрагмент кода:

Expression<Func<TSource, TDest>> expression = model => new TDest{};
// Result: {model => new TestModel(){}}

ReSharper рефакторинг этот фрагмент с RedundantEmptyObjectOrCollectionInitializer установка:

Expression<Func<TSource, TDest>> expression2 = model => new TDest();
// Result: {model => new TestModel()}

после этого, мой код не работает. Какое влияние оказывают фигурные скобки на инициализацию?
нашел в чем разница между new object() и new {} в C#? при переполнении стека, но оба экземпляра выглядят одинаково.

expression.GetType().ToString() равна expression2.GetType().ToString()

в чем разница между этими инициализациями в деревьях выражений?:

var a = model => new TDest{};
var b = model => new TDest();
2 65

2 ответа:

в обычном raw C# ответ будет "ничего". Однако, когда вы включаете деревья выражений, есть разница; как видно здесь

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 {};
}

компилируется как:

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

так один из них включает в себя Expression.MemberInit (С пустым набором MemberBinding элементы) в дополнение к Expression.New. Это может расстроить любого поставщика LINQ (или любой подобный анализ дерева выражений), который этого не ожидает.

ReSharper дает вам лучшее предложение в том, как создать экземпляр TDest класса.

в теории, нет никакой разницы как new TDest () и new TDest {} предоставит вам экземпляр TDest.

однако, когда вы используете выражение инициализации, это потому, что вы хотите установить значения свойств или полей TDest.

class TDest
{
    public string MyProperty { get; set; }
}

таким образом, вы можете инициализировать TDest класс установка значения MyProperty. Например:

// Sample 1
new TDest { MyProperty = "This is the value of my property" };

// Sample 2
new TDest() { MyProperty = "This is the value of my property" };

в вашем случае, ваш класс имеет конструктор без параметров, так как знаки пунктуации {, } или операторов () было бы нормально.

для простых сценариев, где у вас есть конструктор без параметров, вы можете использовать только TDest() короткая форма.

но если бы у вас был, например, класс ниже.

class TDest
{
    readonly ISomeInterface _someService;

    public string MyProperty { get; set; }

    public TDest(ISomeInterface someService)
    {
        _someService = someService;
    }
}

и вы хотели инициализировать MyProperty С чем-то, а не его значение инициализации по умолчанию (null, ссылочные типы), вы можете использовать полную инициализацию объекта. Например:

// Sample 3
new TDest(new MySomeServiceImplementation()) { MyProperty = "This is the value of my property" };

надеюсь, что это помогает!

чтобы иметь лучшую идею, пойти и посмотреть на Инициализаторы Объектов C#.