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#对象初始化器。