usar una son qué programacion miembros metodos los instancia estáticos estaticos estatico cuando clase atributos atributo c# .net generics static

c# - son - ¿Los miembros estáticos de una clase genérica están vinculados a la instancia específica?



qué son los atributos de clase estáticos (6)

Esto es más una documentación que una pregunta real. Esto no parece haber sido abordado en SO aún (a menos que me lo haya perdido), así que aquí va:

Imagine una clase genérica que contiene un miembro estático:

class Foo<T> { public static int member; }

¿Hay una nueva instancia del miembro para cada clase específica, o solo hay una instancia única para todas las clases de tipo Foo?

Se puede verificar fácilmente con un código como este:

Foo<int>.member = 1; Foo<string>.member = 2; Console.WriteLine (Foo<int>.member);

¿Cuál es el resultado y dónde se documenta este comportamiento?


El problema aquí es en realidad el hecho de que las "clases genéricas" no son clases en absoluto.

Las definiciones de clases genéricas son solo plantillas para clases, y hasta que se especifiquen sus parámetros de tipo, son solo una porción de texto (o un puñado de bytes).

En tiempo de ejecución, uno puede especificar un parámetro de tipo para la plantilla, dándole vida y creando una clase del tipo ahora completamente especificado. Es por eso que las propiedades estáticas no abarcan toda la plantilla, y es por eso que no se puede convertir entre List<string> y List<int> .

Esa relación refleja un poco la relación clase-objeto. Al igual que las clases no existen * hasta que crea una instancia de un objeto a partir de ellas, las clases genéricas no existen hasta que crea una clase basada en la plantilla.

PS: es bastante posible declarar

class Foo<T> { public static T Member; }

De esto es bastante obvio que los miembros estáticos no se pueden compartir, ya que T es diferente para diferentes especializaciones.


La implementación de C # de los genéricos está más cerca de C ++. En ambos idiomas, MyClass<Foo> y MyClass<Bar> no comparten miembros estáticos, pero en Java sí lo hacen. En C # y C ++ MyClass<Foo> internamente crea un tipo completamente nuevo en el momento de la compilación, como si los genéricos fueran una especie de macros. Por lo general, puede ver sus nombres generados en el seguimiento de la pila, como MyClass''1 y MyClass''2 . Es por eso que no comparten variables estáticas. En Java, los genéricos se implementan mediante un método más simple de compilación que genera código usando tipos no genéricos y agregando tipos de moldes por todas partes. Así que MyClass<Foo> y MyClass<Bar> no generan dos clases completamente nuevas en Java, sino que ambas son de la misma clase MyClass y es por eso que comparten variables estáticas.


No son compartidos. No estoy seguro de dónde está documentado, pero la advertencia de análisis CA1000 ( No declarar miembros estáticos en tipos genéricos ) advierte contra esto debido al riesgo de complicar el código.


No son realmente compartidos. Porque el miembro no pertenece a la instancia en absoluto. Un miembro de clase estático pertenece a la clase misma. Entonces, si tiene MyClass.Number, es el mismo para todos los objetos MyClass.Number porque ni siquiera depende del objeto. Incluso puede llamar o modificar MyClass.Number sin ningún objeto.

Pero como Foo <int> no es de la misma clase que Foo <cadena>, estos dos números no se comparten.

Un ejemplo para mostrar esto:

TestClass<string>.Number = 5; TestClass<int>.Number = 3; Console.WriteLine(TestClass<string>.Number); //prints 5 Console.WriteLine(TestClass<int>.Number); //prints 3


OMI, debes probarlo, pero creo que

Foo<int>.member = 1; Foo<string>.member = 2; Console.WriteLine (Foo<int>.member);

Será la salida 1 porque creo que, durante la compilación, el compilador crea 1 clase para cada clase genérica que usas (en tu ejemplo: Foo<int> y Foo<string> ).

Pero no estoy 100% seguro =).

Observación: creo que no es un buen diseño ni una buena práctica usar ese tipo de atributos estáticos.


Un campo static se comparte en todas las instancias del mismo tipo . Foo<int> y Foo<string> son dos tipos diferentes. Esto puede ser probado por la siguiente línea de código:

// this prints "False" Console.WriteLine(typeof(Foo<int>) == typeof(Foo<string>));

En cuanto a dónde está documentado esto, lo siguiente se encuentra en la sección 1.6.5 Campos de la Especificación del lenguaje C # (para C # 3):

Un campo estático identifica exactamente una ubicación de almacenamiento. No importa cuántas instancias de una clase se creen, solo hay una copia de un campo estático.

Como se dijo antes; Foo<int> y Foo<string> no son de la misma clase; son dos clases diferentes construidas a partir de la misma clase genérica. Cómo se hace esto se describe en la sección 4.4 del documento mencionado anteriormente:

Una declaración de tipo genérico, por sí misma, denota un tipo genérico no vinculado que se utiliza como un "blueprint" para formar muchos tipos diferentes, mediante la aplicación de argumentos de tipo.