2010-03-28 17 views
89

Aquí es una estructura que estoy tratando de escribir:Constructor de estructuras: "los campos se deben asignar por completo antes de devolver el control a la persona que llama".

public struct AttackTraits 
     { 
      public AttackTraits(double probability, int damage, float distance) 
      { 
       Probability = probability; 
       Distance = distance; 
       Damage = damage; 
      } 

      private double probability; 
      public double Probability 
      { 
       get 
       { 
        return probability; 
       } 
       set 
       { 
        if (value > 1 || value < 0) 
        { 
         throw new ArgumentOutOfRangeException("Probability values must be in the range [0, 1]"); 
        } 
        probability = value; 
       } 
      } 

      public int Damage { get; set; } 

      public float Distance { get; set; } 
     } 

Esto se traduce en los siguientes errores de compilación:

El 'esto' objeto no puede ser utilizado antes de que todos sus campos se asignan a

'AttackTraits.probability' el campo debe ser totalmente asignado antes del control se devueltos a la persona que llama

campo del forro para las automáticamente propiedad 'AttackTraits.Damage' implementado debe ser totalmente asignado antes se devuelve el control a la persona que llama. Considere llamar al constructor predeterminado desde un constructor inicializador.

campo del forro para las automáticamente propiedad 'AttackTraits.Distance' implementado debe ser totalmente asignado antes se devuelve el control a la persona que llama. Considere llamar al constructor predeterminado desde un constructor inicializador.

¿Qué estoy haciendo mal?

Respuesta

26

está configurando el campo probability través de la propiedad Probability, pero el compilador no sabe que la propiedad establece el campo ... por lo que necesita para inicializar explícitamente el campo de probabilidad en sí

public AttackTraits(double probability, int damage, float distance) 
{ 
    this.probability = 0; 
    Distance = distance; 
    Damage = damage; 
} 
+0

Intenté esto. no funcionó para mí, pero estoy usando propiedades automáticas –

+38

@RogerWillcocks, simplemente llame al constructor predeterminado y luego: 'public YourStruct (algunos parámetros): this()' (vea la respuesta de vittore) –

+2

El problema con esta solución. No tiene los beneficios de validación de la propiedad Probabilidad. Y no soluciona todo, porque también necesita cambiar 'Distance' y' Damage' a propiedades no anónimas; de lo contrario, no funcionará. Prefiero la respuesta de @ Chris-Amelinckx como una mejor solución. – hwcverwe

2

Cambio la línea Probability = probability a this.probability = probability

En el futuro elija una convención de nomenclatura diferente para los campos como lo hace para los parámetros. Por ejemplo, delante de todos los campos con un guión bajo, por lo que sólo tiene que llamar esto:

_probability = probability; 

y ver fácilmente lo que está pasando.

+1

pero no realizará la comprobación de validez realizada en el conjunto de propiedades ... –

+0

Sí, simplemente existe un conflicto de nombre feo entre un parámetro y un campo. –

44

intente acceder al campo de probabilidad, no al acceso. En este caso, los accesorios automáticos deberían funcionar también.

No hay forma de que una estructura tenga un constructor sin parámetros, así que considere cambiarla a clase.

La mejor práctica es usar estructuras solo si tienen 16 bytes o menos y son inmutables. Entonces, si va a cambiar los campos del objeto después de la creación, considere refactorizarlo a la clase.

Además, puede cambiar la definición constructor para:

construct(params) : this() 

esto va a eliminar el error, así

+3

Solo FYI, su respuesta funciona, pero parte de su justificación es incorrecta. De hecho, las estructuras SIEMPRE tienen constructores sin parámetros. A diferencia de las clases, el constructor sin parámetros de una estructura no se puede ocultar creando un constructor con parámetros. –

+0

@ joshua.ewer: tienen verdadero, pero está oculto al uso – vittore

+2

No es necesario detallar este punto innecesariamente, pero no solo es perfectamente legal llamar a ese constructor, sino que aparecerá en intellisense como cualquier otro constructor. ¿Puedes proporcionar un caso donde eso no sea cierto? –

260

Si ve este error en una estructura que tiene una propiedad automática, simplemente llame al contructor sin parámetros de su ser parametrizado haciendo : this() siguiente ejemplo:

struct MyStruct 
{ 
    public int SomeProp { get; set; } 

    public MyStruct(int someVal) : this() 
    { 
    this.SomeProp = someVal; 
    } 
} 

llamando: esto() de su declaración de constructor que deje la base La clase ValueType inicializa todos los campos de respaldo para las propiedades automáticas. No podemos hacerlo manualmente en nuestro constructor porque no tenemos acceso al campo de respaldo de una propiedad automática. ValueType es la clase base de todas las estructuras.

+14

Agregando: esto() funcionó para mí –

+4

@ChrisAmelinckx ¿Dónde encuentras todas esas cosas? parece una especie de imaginación de alguien aunque solo funciona de verdad (: – LoneXcoder

+0

Brillante! Esto funcionó para mí. – Contango

Cuestiones relacionadas