2009-08-13 20 views
18

estoy muy nuevo en C# así que por favor tengan paciencia conmigo ...C#: ¿Cómo establecer el valor predeterminado para una propiedad en una clase parcial?

estoy poniendo en práctica una clase parcial, y le gustaría añadir dos propiedades de este modo:

public partial class SomeModel 
{ 
    public bool IsSomething { get; set; } 
    public List<string> SomeList { get; set; } 

    ... Additional methods using the above data members ... 
} 

me gustaría inicialice ambos miembros de datos: IsSomething a True y SomeList a new List<string>(). Normalmente lo haría en un constructor, sin embargo, como es una clase parcial, no quiero tocar el constructor (¿debería?).

¿Cuál es la mejor manera de lograrlo?

Gracias

PS Estoy trabajando en ASP.NET MVC, agregando funcionalidad a un cierto modelo, por lo tanto, la clase parcial.

+2

Esos son alrea dy los valores predeterminados para esos tipos. No necesitas hacer nada. –

+0

Quiero explícito. ¿Qué sucede si quiero "Verdadero" o "nuevo Listado ()"? –

+1

Edité la pregunta para reflejar valores que no son los valores predeterminados "naturales". –

Respuesta

34

Actualización para C# 6

C# 6 ha añadido la posibilidad de asignar un valor por defecto de auto-propiedades. El valor puede ser cualquier expresión (no tiene que ser una constante). He aquí algunos ejemplos:

// Initialize to a string literal 
public string SomeProperty {get;set;} = "This is the default value"; 

// Initialize with a simple expression 
public DateTime ConstructedAt {get;} = DateTime.Now; 

// Initialize with a conditional expression 
public bool IsFoo { get; } = SomeClass.SomeProperty ? true : false; 

respuesta original

propiedades implementadas automáticamente se pueden inicializar en el constructor de la clase, pero no en el propio hotel fenomenal.

public SomeModel 
{ 
    IsSomething = false; 
    SomeList = new List<string>(); 
} 

... o puede utilizar una propiedad respaldado campo (un poco más de trabajo) e inicializar el propio campo ...

private bool _IsSomething = false; 
public bool IsSomething 
{ 
    get { return _IsSomething; } 
    set { _IsSomething = value; } 
} 

Actualización: Mi respuesta anterior no aclara la cuestión de que esto esté en una clase parcial. Mehrdad's answer ofrece la solución de usar un método parcial, que está en línea con mi primera sugerencia. Mi segunda sugerencia de usar propiedades no implementadas automáticamente (propiedades implementadas manualmente?) Funcionará para esta situación.

+0

SomeList = new List **() **; – grenade

+0

Con respecto a su primera sugerencia, ¿se considera una "buena práctica" hacerlo? Sin duda será más fácil, pero se siente como "olor a código" ... –

+0

@RaxL Estoy en la cerca por el olor. La lógica de inicialización es una parte bastante normal del desarrollo OO; siempre que los desarrolladores que trabajan en el sistema sigan las mismas prácticas, entonces no creo que sea un problema. – STW

8

La primera propiedad (IsSomething) es un booleano. Será falso por defecto.

La segunda propiedad, dado que es un tipo de referencia, se convertirá en nulo por defecto sin ningún esfuerzo de su parte. No necesita tocar el constructor, ya que los tipos de referencia (clases) comenzarán automáticamente como null en .NET.

Si desea utilizar un valor no predeterminado, que tendría dos opciones -

En primer lugar, utilizar un campo de almacenamiento de respaldo:

private bool isSomething = true; 
public bool IsSomething { 
    get { return this.isSomething; } 
    set { this.isSomething = value; } 
} 

Segunda opción - agregarlo al constructor.

Tenga en cuenta que la primera opción no tiene gastos generales adicionales, es básicamente lo que hace el compilador cuando utiliza una propiedad automática.

+0

+1 para señalar los diferentes comportamientos de los tipos de valor/referencia. – STW

1

Ambas propiedades ya tienen los valores predeterminados que necesita.

No hay nada de malo en tener un constructor en una clase parcial. Las clases parciales no son de ninguna manera especiales, aparte del hecho de que su código fuente está distribuido en múltiples archivos/declaraciones.

+1

Como señaló Reed en su comentario, los tipos de valor se inicializarán con un valor predeterminado (0 para int, false para bool ...) pero los tipos de referencia se inicializarán en null/Nothing. Entonces, en su caso IsSomething = false y SomeList = null – STW

+0

@Yooder: esta respuesta se proporcionó cuando la pregunta aún pedía los valores predeterminados de False y null. Retracta tu -1, es injusto para @Programming Hero –

+0

¿Moviendo los postes de la meta a mitad del juego? ¡No es justo! –

5

No puede tener dos constructores en dos partes de una clase parcial. Sin embargo, puede utilizar partial methods para lograr algo semejante:

// file1: 
partial void Initialize(); 
public Constructor() { 
    // ... stuff ... initialize part 1 
    Initialize(); 
} 

// file2: 
void Initalize() { 
    // ... further initializations part 2 might want to do 
} 

Si no hay partes de una clase parcial define el método parcial, se omiten todas las llamadas a la misma.

+0

Por desgracia, esto no ayuda si la parte de la clase que tiene el constructor es código generado. – Vaccano

4

Para esto, no utilice la propiedad automático, pero la manera antigua

YourType _yourParameter = yourDefaultValue; 
public YourType YourParameter 
{ 
    get{return _yourParameter;} 
    set{_yourParameter=value;} 
} 
5

ADVERTENCIA para los usuarios de WCF clases parciales

Si usted está tratando de añadir un alojamiento a un proxy de WCF clase (generada por Agregar referencia de servicio) es posible que se sorprenda al descubrir que los campos privados no se inicializan porque al parecer no constructor at all is called.

Si intenta hacer esto (como se sugiere en algunas otras respuestas) no conseguirá nunca denominado:

private bool _sendEmail = true; 

Esto no tiene nada que ver con si el campo está en una clase parcial o no.

Lo que tiene que hacer es agregar un atributo [OnDeserialized] que le permite realizar una inicialización adicional del objeto. Esto es parte de System.Runtime.Serialization, por lo que solo es útil en el contexto de la serialización cuando se usa DataContractSerializer.

public partial class EndOfDayPackageInfo 
{ 
    [OnDeserialized()] 
    public void Init(StreamingContext context) 
    { 
     _sendEmail = true; 
    } 

    private bool _sendEmail; 
    public bool SendEmail 
    { 
     get 
     { 
      return _sendEmail; 
     } 
     set 
     { 
      _sendEmail = value; 
      RaisePropertyChanged("SendEmail"); 
     } 
    } 

}

Otro enfoque es la posibilidad de cargar perezoso 'la propiedad - pero este enfoque es mucho menos elegante.

private bool _sendEmail; 
    private bool _sendEmailInitialized; 

    public bool SendEmail 
    { 
     get 
     { 
      if (!_sendEmailInitialized) 
      { 
       _sendEmailInitialized = true; 
       _sendEmail = true; // default value 
      } 

      return _sendEmail; 
     } 
     set 
     { 
      if (!_sendEmailInitialized) 
      { 
       // prevent unwanted initialization if 'set' is called before 'get' 
       _sendEmailInitialized = true; 
      } 

      _sendEmail = value; 
      RaisePropertyChanged("SendEmail"); 
     } 
    } 
+0

Qué interesante. Tiene sentido de una manera retorcida. – NotMe

+0

ya pero muy confuso al principio. Acabo de descubrir esto hoy y pensé que era un problema vinculante de WPF hasta que finalmente me di cuenta de que era WCF. resulta que llaman a este método que evita llamar a cualquier constructor: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatterservices.getuninitializedobject.aspx –

+0

Gracias, este fue exactamente mi problema. –

2

Para los usuarios de la versión 6.0 de C#, es posible inicializar las propiedades de esta manera:

public bool IsSomething { get; set; } = true; 
public List<string> SomeList { get; set; } = new List<string>(); 
0
private bool _InternalUserContactUpdate = false; 
     public bool InternalUserContactUpdate 
     { 
      get { return _InternalUserContactUpdate; } 
      set { _InternalUserContactUpdate = value; } 
     } 

Luego, cuando se desea anular el valor de condición,

if(!objUserModel.FirstName.ToLower().Equals(entry.Key[0].Attributes.Contains("firstname").ToString().ToLower())) 
     { 
      objUserModel.InternalUserContactUpdate= true; 
     } 

Espero que esto ayude

Cuestiones relacionadas