在c#中,新对象()和新对象{}的区别是什么?

时间:2022-03-13 22:28:44

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:

ReSharper使用冗余antemptyobjectorectioninitializer设置重构这段代码:

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.

在那之后,我的代码就不起作用了。花括号对初始化有什么影响?我发现新对象()和新{}在c#中有什么区别?在堆栈溢出时,但两个实例看起来是相等的。

expression.GetType().ToString() is equal to expression2.GetType().ToString()

gettype ().ToString()等于expression2.GetType().ToString()

What is the difference between these initializations in expression trees?:

表达式树中的这些初始化有什么区别?

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

2 个解决方案

#1


103  

In regular raw C# the answer would be "nothing". However, when you involve expression trees, there is a difference; as can be seen here

在常规的原始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 {};
}

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.

其中一个包含一个表达式。除了Expression.New之外,MemberInit(具有一组空的MemberBinding元素)。这可能会打乱任何LINQ提供程序(或任何类似的表达式树分析),而这些都不是预期的。

#2


5  

ReSharper is giving you a better suggestion in how to instantiate the TDest class.

ReSharper对如何实例化最时髦的类给出了更好的建议。

In theory, there isn't any difference as both new TDest () and new TDest {} will provide you with an instance of TDest.

在理论上,没有任何区别,因为新的TDest()和新的TDest{}将为您提供一个TDest实例。

However, when you use the initialization expression, it's because you want to set values of public properties or fields in TDest.

但是,当您使用初始化表达式时,这是因为您希望在dest中设置公共属性或字段的值。

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

So you could initialize the TDest class setting a value to MyProperty. E.g.:

因此,您可以初始化test类,为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" };

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.

对于具有无参数构造函数的简单场景,只能使用最TDest()短表单。

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.:

你想用一些东西初始化MyProperty而不是它的默认初始化值(null,引用类型),你可以使用完整的对象初始化。例如:

// 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.

要有更好的想法,可以看看c#对象初始化器。

#1


103  

In regular raw C# the answer would be "nothing". However, when you involve expression trees, there is a difference; as can be seen here

在常规的原始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 {};
}

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.

其中一个包含一个表达式。除了Expression.New之外,MemberInit(具有一组空的MemberBinding元素)。这可能会打乱任何LINQ提供程序(或任何类似的表达式树分析),而这些都不是预期的。

#2


5  

ReSharper is giving you a better suggestion in how to instantiate the TDest class.

ReSharper对如何实例化最时髦的类给出了更好的建议。

In theory, there isn't any difference as both new TDest () and new TDest {} will provide you with an instance of TDest.

在理论上,没有任何区别,因为新的TDest()和新的TDest{}将为您提供一个TDest实例。

However, when you use the initialization expression, it's because you want to set values of public properties or fields in TDest.

但是,当您使用初始化表达式时,这是因为您希望在dest中设置公共属性或字段的值。

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

So you could initialize the TDest class setting a value to MyProperty. E.g.:

因此,您可以初始化test类,为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" };

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.

对于具有无参数构造函数的简单场景,只能使用最TDest()短表单。

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.:

你想用一些东西初始化MyProperty而不是它的默认初始化值(null,引用类型),你可以使用完整的对象初始化。例如:

// 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.

要有更好的想法,可以看看c#对象初始化器。