.NET Atributos: Por que GetCustomAttributes () fazer uma nova instância atributo de cada vez?

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

  •  03-07-2019
  •  | 
  •  

Pergunta

Então, eu estava jogando em torno de um pouco mais com atributos em .NET, e percebi que cada chamada para Type.GetCustomAttributes () cria uma nova instância do meu atributo. Por que é que? Gostaria de pensar que a instância atributo seria basicamente um singleton-per-MemberInfo, com 1 instância vinculada ao tipo, PropertyInfo, etc ...

Aqui está o meu código de teste:

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

Agora, se I foram para implementar atributos, seria de esperar que a saída seja:

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

Quando o "carregador de classe" (desculpe, eu tenho mais de um fundo Java, não é 100% certo como .net carrega seus tipos) seria compilar MyClass, e criar uma instância de MyAttribAttribute, e armazená-los juntos em algum lugar. (Provavelmente o Perm Gen na pilha se isso fosse Java) As 2 chamadas para GetCustomAttributes (), então, basta retornar a mesma instância anteriormente criada.

Mas a saída real é:

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

Então ... por quê? Parece que a criação de uma nova instância de todos esses objetos para cada chamada é um pouco excessiva, e não é bom para o gerenciamento de performance / memória. Existe alguma maneira para obter sempre a mesma instância mais e mais?

Alguém tem alguma idéia por que ele foi concebido desta forma?

A razão que eu me importo com nada é porque eu fiz um atributo personalizado que mantém internamente algumas informações de validação, assim, no Atributo Basicamente, eu tenho um "private bool Validado" que eu definido como verdadeiro. O material de validação leva um tempo, então eu não quero para executá-lo o tempo todo. Agora o problema é que, uma vez que cria uma nova instância do atributo cada vez que eu obter os atributos, Validado é sempre "false".

Foi útil?

Solução

Object-criação é barata.

Se você tivesse um atributo como

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

e aplicou-a uma classe como

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

e você recuperou um como

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

e definir algumas propriedades sobre ele como

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

O deve acontecer, e que se acontecer, a próxima vez que você ligou

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

?

Outras dicas

Os atributos não são armazenados na memória como objetos, eles são apenas armazenado como metadados na montagem. Quando você consulta para ele, ele vai ser construído, e voltou, e, geralmente, atributos são descartável objetos assim para o tempo de execução para mantê-los em torno apenas no caso de você precisar deles novamente provavelmente desperdiçar uma grande quantidade de memória.

Em suma, você precisa encontrar outra maneira de armazenar suas informações compartilhadas.

Aqui está o documentação em atributos.

É porque os atributos são salvos em metadados. Atributos deve ser usado para informações como "nome amigável de propriedade", etc ...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top