Attributs .NET: Pourquoi GetCustomAttributes () crée-t-il chaque fois une nouvelle instance d'attribut?

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

  •  03-07-2019
  •  | 
  •  

Question

Je jouais donc un peu plus avec les attributs dans .NET et je me suis rendu compte que chaque appel à Type.GetCustomAttributes () crée une nouvelle instance de mon attribut. Pourquoi donc? Je pense que l’instance d’attribut serait essentiellement un singleton par membre, avec 1 instance liée au type, au PropertyInfo, etc ...

Voici mon code de test:

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();
    }
}
}

Maintenant, si I implémentais des attributs, je m'attendrais à ce que le résultat soit:

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

Où le "class loader" " (désolé, j’ai plus d’arrière-plan Java et je ne suis pas sûr à 100% de la façon dont .net charge ses types) compilerait MyClass, créerait une instance de MyAttribAttribute et les stockerait quelque part. (Probablement le Perm Gen du tas s'il s'agit de Java) Les 2 appels à GetCustomAttributes () renverraient alors simplement la même instance créée précédemment.

Mais la sortie réelle est:

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

Alors ... pourquoi? Il semble que créer une nouvelle instance de tous ces objets pour chaque appel est un peu excessif et ne convient pas à la gestion des performances / de la mémoire. Existe-t-il un moyen de toujours avoir la même instance encore et encore?

Quelqu'un at-il une idée de la raison pour laquelle il a été conçu de cette façon?

La raison pour laquelle je me soucie du tout est que j'ai créé un attribut personnalisé qui contient certaines informations de validation en interne. Par conséquent, dans l'attribut, j'ai un "bool privé validé". que je mets au vrai. La validation prend un certain temps, je ne veux donc pas l'exécuter à chaque fois. Maintenant, le problème est que, puisqu'il crée une nouvelle instance de l'attribut chaque fois que je reçois les attributs, Validated est toujours "faux".

Était-ce utile?

La solution

La création d’objets n’est pas chère.

Si vous aviez un attribut tel que

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

et l'a appliqué à une classe comme

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

et vous en avez récupéré un comme

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

et vous définissez des propriétés comme

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

que devrait-il se produire et que se produirait la prochaine fois que vous avez appelé

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

?

Autres conseils

Les attributs ne sont pas stockés en mémoire en tant qu'objets, ils sont uniquement stockés en tant que métadonnées dans l'assemblage. Lorsque vous l'interrogez, il est construit et renvoyé. Les attributs sont généralement des objets à jeter. Par conséquent, les conserver au moment de l'exécution, au cas où vous en auriez besoin, gaspilleriez probablement beaucoup de mémoire.

En bref, vous devez trouver un autre moyen de stocker vos informations partagées.

Voici la documentation sur attributs.

C'est parce que les attributs sont enregistrés dans les métadonnées. Les attributs doivent être utilisés pour des informations telles que "Nom convivial de la propriété", etc ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top