2012-10-01 31 views
17

Tengo una estructura que (para los fines de esta pregunta) imita el tipo Point incorporado.¿Cómo puedo verificar si una estructura ha sido instanciada?

Necesito comprobar que se ha instanciado antes de usarlo. Cuando era Point, que podría hacer esto:

if (this.p == null) 

Pero que ahora genera el siguiente error:

Operator '==' cannot be applied to operands of type 'ProportionPoint' and '<null>'

¿Cómo puedo comparar mi estructura contra nula? ¿Hay alguna otra forma de verificar la instanciación?

+1

¿Por qué usas struct contra clase? –

Respuesta

25

A struct es un tipo de valor, nunca es nulo.

Puede consultar contra default(ProportionPoint), que es el valor predeterminado de la estructura (por ejemplo, cero). Sin embargo, por un punto, es posible que el valor predeterminado, el origen, también sea un valor "válido".

En su lugar, puede utilizar un Nullable<ProportionPoint>.

+0

Gracias. Estás al tanto sobre el origen = valor predeterminado. Podría haber usado el valor nullable, pero me di cuenta de que el comportamiento que deseo coincide con una clase mejor que una estructura. –

+2

Y eso, o específicamente la falta de eso, es la razón por la cual una cantidad alarmante de instalaciones del NHS estaban "localizadas" una vez al sur de Ghana y al oeste de Gabón. – CJPN

2

A struct no puede ser nulo. Es un valor tipo, no es un tipo de referencia. Debe verificar las propiedades con los valores predeterminados. Algo como:

if(p.X == 0 && p.Y == 0) 
2

Una estructura nunca puede ser nula, por lo que no se puede comparar con nulo. Y una estructura siempre se inicializa, si no es usted, entonces el compilador con valores predeterminados.

7

las estructuras son tipos de valores y nunca pueden ser nulas a diferencia de los tipos de referencia. Puede consultar el valor predeterminado:

if (this.p == default(ProportionPoint)) 
+8

Tenga en cuenta que la comprobación del valor predeterminado no le permitirá diferenciar entre un valor "no inicializado" y un valor "inicializado correctamente con valores predeterminados" (por ejemplo, (0, 0)) –

+9

@DarinDimitrov No funciona para mí. El operador '==' no se puede aplicar a operandos del tipo 'Vhdx.RegionTableEntry' y 'Vhdx.RegionTableEntry'. –

+1

No funciona. Debe usar el operador 'Igual', no' == ' – toddmo

-1

Las variables de estructura no pueden ser nulas, una opción sería declararla como anulable.

1

Utilice un anulable:

ProportionPoint? p1 = null; 
if (p1 == null) ... 

o

if (!p1.HasValue) ... 
1

A diferencia de una variable o valor de un tipo de referencia, que es una referencia a cero o uno instancias de ese tipo, una struct variable o valor es instancia struct. Si uno tiene un bloque de código que comienza con {Point myPoint; ...}, y nada en el bloque se cierra sobre MyPoint (el cierre ocurre cuando hay un yield return dentro de un bloque, o cuando un método lambda o anónimo usa una variable de un bloque envolvente), entonces un instancia de Point surgirá en algún momento antes de que la ejecución ingrese al bloque, y puede dejar de existir en cualquier momento después de que la ejecución abandone el bloque. En cualquier contexto donde uno puede hacer uso de una variable tipo struct, la estructura existe.

La razón por la cual se considera que todos los tipos de estructura tienen un constructor predeterminado que no hace nada es que los tipos de estructura existen implícitamente. Cuando uno realiza una declaración como Point[] myPoints = new Point[100];, crea una matriz llena de cero de 100 Point estructuras; en el proceso, 100 instancias puntuales llenas de cero aparecen instantáneamente.En C++, si un tipo tiene un constructor, la creación de una matriz de ese tipo llamará al constructor en cada elemento de la matriz en secuencia antes de que a cualquier código se le dé acceso a la matriz por un tiempo. Si se lanza una excepción al construir cualquier elemento, el código generado por el compilador ejecutará el destructor determinista en cada elemento que se haya creado con éxito antes de que la matriz se evapore. Si bien esta es una característica muy poderosa, incluirla dentro de .net habría complicado sustancialmente el Framework.

3

porque p es struct, nunca será nulo, por lo que debe compararlo con su valor predeterminado. Para verificar la equivalencia entre su valor y el valor predeterminado. Si utiliza == obtendrá

cannot be applied to operands of type 'ProportionPoint' and 'ProportionPoint' error 

debido estructuras no reciben una implementación de == por defecto. lo que es necesario sobrecargar el == y = operadores en su estructura como esta:

public static bool operator ==(firstOperand op1, secondOperand2 op2) 
{ 
    return op1.Equals(op2); 
} 

public static bool operator !=(firstOperand op1, secondOperand2 op2) 
{ 
    return !op1.Equals(op2); 
} 

y luego:

if (this.p == default(ProportionPoint)) 

otra opción es utilizar directamente Igual:

f (this.p.Equals.default(ProportionPoint)) 
-1

Hice un método de extensión que solo funciona con structs:

public static bool IsNull<T>(this T source) where T:struct 
{ 
    return source.Equals(default(T)); 
} 
convención

Calling:

if(myStruct.IsNull()) 
    DoSomething(); 

entiendo que no es realmente controla si está null. Sin embargo, si le doy un nombre más preciso, como IsEmpty o IsDefault, en seis meses me olvidaría de que está allí y al ver la lista de métodos disponibles, no la elije. No es técnicamente un cheque nulo; pero conceptualmente lo es.

-1

Las estructuras no pueden ser nulas, pero la solución de comprobar una estructura contra su valor predeterminado puede dar un falso negativo si realmente desea almacenar valores equivalentes a los valores predeterminados en cualquier punto.

(Por ejemplo, una estructura con el valor (0,0,0) podría ser un defecto tal cual, o se podría almacenar el punto de origen en el espacio 3D.)

Otro enfoque que evite este problema falso negativo sería simplemente añadir otra propiedad de la estructura, por ejemplo un bool o int - para rastrear si los datos realmente han sido almacenados en él. Luego, cualquier constructor que inicialice la estructura con datos reales establece este valor en verdadero/1. En la estructura predeterminada, este valor seguirá siendo falso/0, por lo que la comprobación en contra de default(MyStruct) nunca debería darle un falso negativo incluso si todos los demás datos almacenados en él coinciden con los valores predeterminados.

public Struct MyStruct { 
    public float x { get; private set; } 
    public bool initialized { get; private set; } 

    public MyStruct(float _x){ 
     x=_x; 
     initialized = true; 
    } 
} 
Cuestiones relacionadas