2011-01-23 32 views
8

considerar la siguiente clase escrito en C# .NET 4.0 (típicamente se encuentran en una clase nhibernate):Sintaxis para los miembros virtuales

public class CandidateEntity : EntityBase 
{ 
    public virtual IList<GradeEntity> Grades { get; set; } 

    public CandidateEntity() 
    { 
     Grades = new List<GradeEntity>(); 
    } 
} 

Esta línea se hace una advertencia "llamada de miembro virtual en el constructor" bien fundada. ¿Dónde debo inicializar esta colección?

Regards,

+0

¿Duplicado? [Llamada de miembro virtual en un constructor] (http://stackoverflow.com/questions/119506/virtual-member-call-in-a-constructor) –

+2

@Tomas, no necesariamente un duplicado ya que esa pregunta era más sobre por qué es mala para inicializar un miembro virtual de un constructor. Buena lectura para OP sin embargo. – Vadim

Respuesta

11

El campo de respaldo es de una sola dirección. Otra es usar un setter privado. Esto funciona bien en nHibernate.

public virtual IList<GradeEntity> Grades { get; private set; } 

public CandidateEntity() 
{ 
    Grades = new List<GradeEntity>(); 
} 
9

utiliza un campo de respaldo e inicializar el campo de respaldo en el constructor. Alternativamente, haz que la clase sea sellada.

private IList<GradeEntity> _grades 

public virtual IList<GradeEntity> Grades 
{ 
    get { return _grades; } 
    set { _grades = value; } 
} 

public CandidatesEntity() 
{ 
    _grades = new List<GradeEntity>(); 
} 
+0

¿Entonces la respuesta sobre cómo inicializar un miembro virtual es no hacerlo virtual? – tenor

+0

Esto tiene sentido, me pregunto por qué no se me había ocurrido antes. Gracias. – Calin

+0

@tenor, Grades sigue siendo virtual y las clases derivadas pueden anular la implementación como lo deseen. Lea este http://stackoverflow.com/questions/119506/virtual-member-call-in-a-constructor para obtener una buena explicación sobre por qué es malo inicializar miembros virtuales en un constructor – Vadim

-1

Crear un método reemplazable (virtual) llamado OnInit o algo similar e inicializar Grade allí, a continuación, llamar OnInit desde el constructor.

La advertencia está ahí para informarle que está creando un comportamiento que será difícil de anular para los implementadores.

+0

Eso no es cierto. El compilador le advierte sobre un posible problema real si esta clase se hereda.Lo que sugiere solo oculta el problema del análisis estático en tiempo de compilación. –

+0

No, lo que sugiero es dar a los implementadores la oportunidad de anular el mal comportamiento que el compilador intenta advertirles. Consulte http://stackoverflow.com/questions/119506/virtual-member-call-in-a-constructor/119543#119543 – tenor

+0

@ jdv-Jan de Vaan. No importa. Tienes razón. No entendí * por qué * está mal tener un constructor que llame a un miembro virtual. – tenor

0

Si hace la clase sealed, tampoco recibirá la advertencia (porque el problema es solo un problema si hereda esta clase y anula el miembro).

Edición después comentario OP:

Ah, cierto. Normalmente encuentro esto solo cuando trato con miembros virtuales heredados. La respuesta de Yads es probablemente la más útil para ti.

Tenga en cuenta que no es necesario que la propiedad sea virtual. Considere esto:

List<Grade> Grades { 
    get { return _grades; } 
    set { _grades = value; OnGradesChanged(); } 

protected virtual OnGradesChanged() 
{ } 

Por lo general, usted no desea almacenar el Grades de una manera diferente en la clase derivada. Solo necesita hacer algunas actualizaciones cuando cambie. De esta manera, proporciona más orientación a la clase derivada, y está seguro de que puede confiar en el campo de respaldo.

P.S. ¿Sabía que las personas pueden editar List<Grade> sin que sus clases lo vean? Debe considerar usar ObservableCollection que incluye un evento cuando la colección se cambia externamente. En ese caso, solo necesita exponer una propiedad readonly Grades.

+0

si hago que la clase sea sellada No puedo tener ninguna propiedad virtual en ella :( – Calin

+0

Jan sugerencias interesantes. Creo que OP está usando NHibernate o algún tipo de marco ORM que requiere que todos los miembros sean virtuales, mientras que estas sugerencias son definitivamente útiles en en muchas situaciones, es probable que esté limitado por restricciones de partido en 3D. – Vadim

Cuestiones relacionadas