Atributos .NET: ¿Por qué GetCustomAttributes () crea una nueva instancia de atributo cada vez?

StackOverflow https://stackoverflow.com/questions/417275

  •  03-07-2019
  •  | 
  •  

Pregunta

Así que estaba jugando un poco más con los atributos en .NET, y me di cuenta de que cada llamada a Type.GetCustomAttributes () crea una nueva instancia de mi atributo. ¿Porqué es eso? Creo que la instancia de atributo sería básicamente un singleton por MemberInfo, con 1 instancia vinculada a Type, PropertyInfo, etc ...

Aquí está mi código de prueba:

using System;

namespace AttribTest
{
[AttributeUsage(AttributeTargets.Class)]
class MyAttribAttribute : Attribute
{
    public string Value { get; set; }

    public MyAttribAttribute()
        : base()
    {
        Console.WriteLine("Created MyAttrib instance");
    }
}

[MyAttrib(Value = "SetOnClass")]
class MyClass
{
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Getting attributes for MyClass.");
        object[] a = typeof(MyClass).GetCustomAttributes(false);
        ((MyAttribAttribute)a[0]).Value = "a1";

        Console.WriteLine("Getting attributes for MyClass.");
        a = typeof(MyClass).GetCustomAttributes(false);
        Console.WriteLine(((MyAttribAttribute)a[0]).Value);

        Console.ReadKey();
    }
}
}

Ahora, si I implementara atributos, esperaría que el resultado fuera:

Created MyAttrib instance
Getting attributes for MyClass.
Getting attributes for MyClass.
a1

Donde el " cargador de clases " (lo siento, tengo más antecedentes de Java, no estoy 100% seguro de cómo .net carga sus tipos) compilaría MyClass, crearía una instancia de MyAttribAttribute y los almacenaría juntos en algún lugar. (probablemente el Perm Gen en el montón si esto fuera Java) Las 2 llamadas a GetCustomAttributes () solo devolverían la misma instancia creada anteriormente.

Pero el resultado real es:

Getting attributes for MyClass.
Created MyAttrib instance
Getting attributes for MyClass.
Created MyAttrib instance
SetOnClass

Entonces ... ¿por qué? Parece que crear una nueva instancia de todos estos objetos para cada llamada es un poco excesivo y no es bueno para la gestión del rendimiento / memoria. ¿Hay alguna forma de obtener siempre la misma instancia una y otra vez?

¿Alguien tiene alguna idea de por qué fue diseñado de esta manera?

La razón por la que me importa es porque hice un atributo personalizado que internamente contiene cierta información de validación, por lo que en el atributo básicamente tengo un "bool privado Validado". que puse en verdad El proceso de validación lleva un tiempo, por lo que no quiero ejecutarlo todo el tiempo. Ahora el problema es que, dado que crea una nueva instancia del atributo cada vez que obtengo los atributos, Validado siempre es "falso".

¿Fue útil?

Solución

La creación de objetos es barata.

Si tuviera un atributo como

public class MyAttribute : Attribute {
    public virtual string MyText { get; set; }
}

y lo aplicó a una clase como

[MyAttribute(MyText="some text")]
public class MyClass {
}

y recuperaste uno como

var attr =
    typeof(MyClass).GetCustomAttributes(typeof(MyAttribute), false)
    .Cast<MyAttribute>().Single();

y configura algunas propiedades como

attr.MyText = "not the text we started with";

qué debería suceder, y qué sucedería, la próxima vez que llame

Console.WriteLine(
    typeof(MyClass).GetCustomAttributes(typeof(MyAttribute), false)
    .Cast<MyAttribute>().Single().Name
);

?

Otros consejos

Los atributos no se almacenan en la memoria como objetos, solo se almacenan como metadatos en el ensamblado. Cuando lo consulta, se construirá y se devolverá, y generalmente los atributos son objetos descartables, por lo que el tiempo de ejecución los mantendrá en caso de que los necesite nuevamente probablemente desperdicie mucha memoria.

En resumen, necesita encontrar otra forma de almacenar su información compartida.

Aquí está la documentación en atributos.

Es porque los atributos se guardan en metadatos. Los atributos deben usarse para información como "nombre de propiedad fácil de usar", etc. ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top