web-dev-qa-db-fra.com

Quelle est la différence entre new Object () et new Object {} dans les expressions en C #

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();
65
cSteusloff

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.

104
Marc Gravell

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

5
Alex.H