2010-12-12 23 views
40

Lo miembro debería aplicar en mi estructura arbitraria para hacer posible la siguiente asignación:¿Cómo inicializar struct?

public struct MyStruct { 
    String s; 
    Int length; 
} 

MyStruct myStruct = new MyStruct { s = "Hello", length = 5 }; 

// Now, I want the following code to set the 's' to "Lol" and the 
// length to 3 (length of "Lol"). The second part should be done 
// automatically. 
myStruct = "Lol"; // Or myStruct = String("Lol"); 

¿Cómo debe hacerse esto?

+4

No haga estructuras mutables. http://stackoverflow.com/questions/441309/why-are-mutable-structs-evil – Ani

+0

'String' s ya conoce su longitud. ¿Por qué necesitarías una estructura como esta? –

+0

@Karl Knechtel: Supongo que es un ejemplo para mostrar el principio. El código que se muestra ni siquiera compila ... – Guffa

Respuesta

72

Utiliza un operador implícito que convierte el valor de cadena a un valor de estructura:

public struct MyStruct { 
    public string s; 
    public int length; 

    public static implicit operator MyStruct(string value) { 
    return new MyStruct() { s = value, length = value.Length }; 
    } 

} 

Ejemplo:

MyStruct myStruct = "Lol"; 
Console.WriteLine(myStruct.s); 
Console.WriteLine(myStruct.length); 

Salida:

Lol 
3 
+0

el problema que puedo ver aquí es una desvirtualización de struct ... cuando usas el operador 'nuevo' para devolver la estructura, este operador colocará los datos en el montón ... así que tal vez sea mejor usar este código como una clase estática (por lo que hay una desambiguación de código para el programador) ... y las cosas ganan coherencia ... – ZEE

+0

@ZEE: El operador 'new' no importa una asignación de pila para una estructura. En realidad, no hay ningún constructor sin parámetros para llamar, solo es sintaxis C# para crear un valor de estructura. – Guffa

0

Su estructura puede tener métodos y propiedades ... ¿por qué no tratar

public struct MyStruct { 
    public string s; 
    public int length { return s.Length; } 
} 

Corrección @ respuesta de Guffa muestra que es posible ... más información aquí: http://www.codeproject.com/KB/cs/Csharp_implicit_operator.aspx

+0

Sí, es posible. – Guffa

+0

@Guffa: Respuesta interesante ... No consideré el operador implícito. –

4
  1. se "longitud" nunca desviarse de la longitud real de la "s". Si la respuesta es no, entonces no necesita almacenar la longitud, porque las cadenas ya almacenan su longitud, y puede simplemente llamar a la longitud.

  2. Para obtener la sintaxis que solicitó, se puede implementar un operador "implícita" de esta manera:

    static implicit operator MyStruct(string s) { 
        return new MyStruct(...); 
    } 
    
  3. El operador implícita va a funcionar, independientemente de si usted hace su estructura mutable o no.

7

Tipos de estructura deben, cuando sea posible, o bien han de su estado encapsulado en campos públicos que de forma independiente se puede establecer en cualquier valor que son válidos para su respectivo tipo, o de lo contrario se comportan como un solo valor unificado que puede solo apostar a través de constructor, fábrica, método o, de lo contrario, pasar una instancia de la estructura como un parámetro explícito ref a uno de sus métodos públicos. Al contrario de lo que afirman algunas personas, no hay nada de malo en que una estructura tenga campos públicos, si se supone que representa un conjunto de valores que pueden ser manipulados individualmente o transferidos como un grupo (por ejemplo, las coordenadas de un punto). Históricamente, ha habido problemas con estructuras que tenían entidades públicas de creación de propiedades, y el deseo de evitar campos públicos (lo que implica que los instaladores deberían usarse en su lugar) ha llevado a algunas personas a sugerir que las estructuras mutables deben evitarse por completo, pero los campos no tienen problemas que las propiedades tenían. De hecho, una estructura de campo expuesto es la representación ideal para una colección suelta de variables independientes, ya que es solo una colección suelta de variables.

En su ejemplo particular, sin embargo, parece que los dos campos de su estructura probablemente no se supone que sean independientes. Hay tres maneras en que su estructura sensiblemente podría diseñarse:

  • que podría tener el único campo público sea la cadena, y luego tener una propiedad de sólo lectura "ayudante" llama length que informaría de su longitud si la cadena no es nulo, o devuelve cero si la cadena es nula.

  • Puede hacer que la estructura no exponga ningún campo público, definidor de propiedad o método de mutación, y que el contenido del único campo, una cadena privada, se especifique en el constructor del objeto. Como se indicó anteriormente, length sería una propiedad que informaría la longitud de la cadena almacenada.

  • Puede hacer que la estructura no exponga ningún campo público, establecimiento de propiedades o métodos de mutación, y tiene dos campos privados: uno para la cadena y otro para la longitud, ambos se establecerán en un constructor que tome una cuerda, la almacena, mide su longitud y la almacena. La determinación de la longitud de una cadena es lo suficientemente rápida como para que probablemente no valga la pena calcularla y almacenarla en caché, pero podría ser útil tener una estructura que combinara una cadena y su valor GetHashCode.

Es importante ser consciente de un detalle en relación con el tercer diseño, sin embargo: si el código no-hilo hace que una instancia de la estructura para ser leído mientras que otro hilo está escribiendo a la misma, que puede causar la creación accidental de una instancia de struct cuyos valores de campo son inconsistentes. Los comportamientos resultantes pueden ser un poco diferentes de los que se producen cuando las clases se utilizan de forma no segura para hilos. Cualquier código que tenga algo que ver con la seguridad debe tener cuidado de no suponer que los campos de estructura estarán en un estado consistente, ya que el código malicioso, incluso en un entorno de "confianza total", puede generar fácilmente estructuras cuyo estado es inconsistente si eso es lo que ocurre quiere hacer

PS - Si desea que su estructura para ser inicializado usando un encargo de una cadena, se recomienda usar un operador de conversión implícita y haciendo Length ser una propiedad de sólo lectura que devuelve la longitud del subyacente cadena si no es nulo, o cero si la cadena es nula.

+1

Aunque hagas algunos puntos interesantes, esto en realidad no responde la pregunta. –

+0

No noté la última tarea, solo la primera. Para permitir esto último, puede definir un operador de conversión implícita de 'String' a su tipo de estructura. Si lo hace, puede desear que 'Length' sea una propiedad de solo lectura que simplemente informa la longitud del campo de cadena asignado, o cero si ese campo es' nulo'. – supercat

+0

Debe incluir eso en su respuesta. Eso lo convertiría en una respuesta real. Y una vez que lo edite, podré retirar mi voto downvote. –