次のコードスニペットがあります。
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()}
その後、私のコードは機能しません。中括弧は初期化にどのような影響を与えますか?
見つかったC#のnew object()
とnew {}
の違いは?スタックオーバーフローでは、両方のインスタンスが同じように見えます。
expression.GetType().ToString()
はexpression2.GetType().ToString()
と等しい
式ツリーのこれらの初期化の違いは何ですか?:
var a = model => new TDest{};
var b = model => new TDest();
通常の生の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);
}
そのため、それらの1つには、Expression.MemberInit
に加えて、Expression.New
(MemberBinding
要素の空のセット)が含まれます。これは、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#Object Initializersをご覧ください。