Attributi .NET: Perché GetCustomAttributes () crea ogni volta una nuova istanza di attributo?

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

  •  03-07-2019
  •  | 
  •  

Domanda

Quindi stavo giocando un po 'di più con gli attributi in .NET e mi sono reso conto che ogni chiamata a Type.GetCustomAttributes () crea una nuova istanza del mio attributo. Perché? Penserei che l'istanza dell'attributo sarebbe sostanzialmente un singleton-per-MemberInfo, con 1 istanza associata a Type, PropertyInfo, ecc ...

Ecco il mio codice di prova:

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

Ora se I dovesse implementare gli attributi, mi aspetterei che l'output sia:

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

Dove il caricatore di classe " " (scusate, ho più di uno sfondo Java, non sono sicuro al 100% di come .net carica i suoi tipi) compilerebbe MyClass, creerebbe un'istanza di MyAttribAttribute e li memorizzerebbe insieme da qualche parte. (probabilmente la Perm Gen nell'heap se fosse Java) Le 2 chiamate a GetCustomAttributes () restituirebbero quindi la stessa istanza creata in precedenza.

Ma l'output effettivo è:

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

Quindi ... perché? Sembra che creare una nuova istanza di tutti questi oggetti per ogni chiamata sia un po 'eccessivo e non sia buono per la gestione delle prestazioni / memoria. C'è un modo per ottenere sempre la stessa istanza più volte?

Qualcuno ha qualche idea sul perché sia ??stato progettato in questo modo?

Il motivo per cui mi interessa a tutti è perché ho creato un attributo personalizzato che contiene internamente alcune informazioni di convalida, quindi nell'attributo ho fondamentalmente un bool "quotato privato" convalidato " che ho impostato su vero. Il processo di convalida richiede un po 'di tempo, quindi non voglio eseguirlo ogni volta. Ora il problema è che dal momento che crea una nuova istanza dell'attributo ogni volta che ottengo gli attributi, Validated è sempre " false " ;.

È stato utile?

Soluzione

La creazione di oggetti è economica.

Se avevi un attributo come

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

e applicato a una classe come

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

e ne hai recuperato uno come

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

e ci imposti alcune proprietà come

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

cosa dovrebbe e cosa succederebbe , la prossima volta che hai chiamato

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

Altri suggerimenti

Gli attributi non vengono archiviati in memoria come oggetti, ma solo come metadati nell'assembly. Quando lo richiedi, verrà costruito e restituito, e di solito gli attributi sono oggetti usa e getta, quindi il runtime li terrà nel caso in cui ne avessi bisogno di nuovo, probabilmente sprecherebbe molta memoria.

In breve, devi trovare un altro modo per archiviare le tue informazioni condivise.

Ecco la documentazione su attributi.

È perché gli attributi sono salvati in metadati. Gli attributi devono essere utilizzati per informazioni come "nome descrittivo della proprietà", ecc ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top