c# - lazy - Establecer propiedades mediante la inicialización de objetos o no: ¿Alguna diferencia?
new list object c# (5)
Como otros han dicho, no, no hay diferencia. Tenga en cuenta que el primer ejemplo no utiliza un constructor para esos argumentos. Está utilizando la función de lenguaje "inicializador de objetos" presentada en C # 3.0. El constructor al que se llama es el constructor sin parámetros predeterminado al igual que el segundo ejemplo.
Los dos ejemplos compilan hasta el mismo código IL y hacen exactamente lo mismo. El primer ejemplo es simplemente azúcar sintáctica para realizar la tarea <opinión> de una manera más fácil y más expresiva </ opinión>.
Aquí hay una pregunta simple: ¿Hay alguna diferencia (de rendimiento) entre esto?
Person person = new Person()
{
Name = "Philippe",
Mail = "[email protected]",
};
y esto
Person person = new Person();
person.Name = "Philippe";
person.Mail = "[email protected]";
Puedes imaginar un objeto más grande con más propiedades.
En lo que respecta al rendimiento, no hay una diferencia significativa, como han demostrado otras respuestas.
Sin embargo, la creación de un objeto utilizando un inicializador con 2 parámetros me parece que usted declara su intención a cualquiera que la use, formando un "contrato" que dice: "estos 2 parámetros son los mínimos para la funcionalidad de la clase" (aunque el la forma correcta de expresar esa intención sería usar un constructor).
Tiendo a pensar en la sintaxis del inicializador de esta manera, aunque es más o menos solo azúcar sintáctica. Uso una combinación de ambas sintaxis en mi código. Pero, de nuevo, ese es mi estilo personal.
No. La primera forma es nueva en .NET 3.5 pero el segundo ejemplo es para versiones anteriores de C #.
Son casi exactamente equivalentes, excepto que el primer método (usando un inicializador de objetos ) solo funciona en C # 3.0 y más reciente. Cualquier diferencia de rendimiento es solo menor y no vale la pena preocuparse.
Producen un código IL casi idéntico. El primero da esto:
.method private hidebysig instance void ObjectInitializer() cil managed
{
.maxstack 2
.locals init (
[0] class Person person,
[1] class Person <>g__initLocal0)
L_0000: newobj instance void Person::.ctor()
L_0005: stloc.1
L_0006: ldloc.1
L_0007: ldstr "Philippe"
L_000c: callvirt instance void Person::set_Name(string)
L_0011: ldloc.1
L_0012: ldstr "[email protected]"
L_0017: callvirt instance void Person::set_Mail(string)
L_001c: ldloc.1
L_001d: stloc.0
L_001e: ldloc.0
L_001f: callvirt instance string [mscorlib]System.Object::ToString()
L_0024: pop
L_0025: ret
}
El segundo da esto:
.method private hidebysig instance void SetProperties() cil managed
{
.maxstack 2
.locals init (
[0] class Person person)
L_0000: newobj instance void Person::.ctor()
L_0005: stloc.0
L_0006: ldloc.0
L_0007: ldstr "Philippe"
L_000c: callvirt instance void Person::set_Name(string)
L_0011: ldloc.0
L_0012: ldstr "[email protected]"
L_0017: callvirt instance void Person::set_Mail(string)
L_001c: ldloc.0
L_001d: callvirt instance string [mscorlib]System.Object::ToString()
L_0022: pop
L_0023: ret
}
Como puede ver, se genera código casi idéntico. Vea a continuación el código exacto de C # que compilé.
Las mediciones de rendimiento muestran resultados muy similares con una mejora de rendimiento muy pequeña para usar la sintaxis del inicializador de objetos:
Method Iterations per second ObjectInitializer 8.8 million SetProperties 8.6 million
Código que utilicé para probar el rendimiento:
using System;
class Person
{
public string Name { get; set; }
public string Mail { get; set; }
}
class Program
{
private void ObjectInitializer()
{
Person person = new Person()
{
Name = "Philippe",
Mail = "[email protected]",
};
person.ToString();
}
private void SetProperties()
{
Person person = new Person();
person.Name = "Philippe";
person.Mail = "[email protected]";
person.ToString();
}
private const int repetitions = 100000000;
private void Time(Action action)
{
DateTime start = DateTime.UtcNow;
for (int i = 0; i < repetitions; ++i)
{
action();
}
DateTime end = DateTime.UtcNow;
Console.WriteLine(repetitions / (end - start).TotalSeconds);
}
private void Run()
{
Time(ObjectInitializer);
Time(SetProperties);
Console.WriteLine("Finished");
Console.ReadLine();
}
private static void Main()
{
new Program().Run();
}
}
Una cosa adicional que vale la pena destacar es esta:
Si no maneja una excepción en su constructor, obtendrá una TypeInitializationException. Si bien eso puede no parecer tan malo, la verdad es que oculta la verdadera causa del problema y hace que sea más difícil rastrearlo.
Si, por otro lado, usa un inicializador de objetos, está invocando cada propiedad individualmente fuera del constructor, y cualquier excepción lanzada será muy clara y muy evidente: no será enmascarada por TypeInitializationException.
En general, es una mala idea lanzar excepciones en un constructor. Si desea evitar ese escenario, vaya con el inicializador.