J'ai l'extrait de code suivant:
Expression<Func<TSource, TDest>> expression = model => new TDest{};
// Result: {model => new TestModel(){}}
ReSharper refactoring cet extrait avec le paramètre RedundantEmptyObjectOrCollectionInitializer
:
Expression<Func<TSource, TDest>> expression2 = model => new TDest();
// Result: {model => new TestModel()}
Après cela, mon code ne fonctionne pas. Quelle influence les accolades ont-elles sur l'initialisation?
J'ai trouvé Quelle est la différence entre new object()
et new {}
En C #? sur le dépassement de pile, mais les deux instances semblent égales.
expression.GetType().ToString()
est égal à expression2.GetType().ToString()
Quelle est la différence entre ces initialisations dans les arbres d'expression?
var a = model => new TDest{};
var b = model => new TDest();
En C # brut normal, la réponse serait "rien". Cependant, lorsque vous impliquez des arbres d'expression, il y a une différence. comme on peut le voir ici
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 {};
}
compile en tant que:
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);
}
Donc, l'un d'eux implique un Expression.MemberInit
(avec un ensemble vide de MemberBinding
éléments) en plus de Expression.New
. Cela peut perturber tout fournisseur LINQ (ou toute analyse d'arborescence d'expression similaire) qui ne s'y attend pas.
ReSharper vous donne une meilleure suggestion sur la manière d'instancier la classe TDest
.
En théorie, il n'y a pas de différence puisque new TDest ()
et new TDest {}
Vous fourniront une instance de TDest
.
Cependant, lorsque vous utilisez l'expression d'initialisation, c'est parce que vous souhaitez définir les valeurs de propriétés ou de champs publics dans TDest
.
class TDest
{
public string MyProperty { get; set; }
}
Vous pouvez donc initialiser la classe TDest
en définissant une valeur sur MyProperty
. Par exemple.:
// Sample 1
new TDest { MyProperty = "This is the value of my property" };
// Sample 2
new TDest() { MyProperty = "This is the value of my property" };
Dans votre cas, votre classe a un constructeur sans paramètre, donc, les ponctuateurs {, }
Ou les opérateurs ()
Iraient bien.
Pour les scénarios simples dans lesquels vous avez un constructeur sans paramètre, vous ne pouvez utiliser que la forme abrégée TDest()
.
Mais si vous aviez par exemple la classe ci-dessous.
class TDest
{
readonly ISomeInterface _someService;
public string MyProperty { get; set; }
public TDest(ISomeInterface someService)
{
_someService = someService;
}
}
Et vous vouliez initialiser MyProperty
avec quelque chose plutôt que sa valeur d’initialisation par défaut (null, types de référence), vous pouvez utiliser l’initialisation complète de l’objet. Par exemple.:
// Sample 3
new TDest(new MySomeServiceImplementation()) { MyProperty = "This is the value of my property" };
J'espère que ça aide!
Pour avoir une meilleure idée, allez jeter un oeil à initialiseurs d'objet C #.