Pergunta

Existe alguma maneira de acessar o campo de apoio de uma propriedade para fazer validação, alteração de rastreamento etc.?

É possível algo como o seguinte? Se não há planos de tê -lo no .NET 4 / C# 4?

public string Name
{
    get;
    set
    {
        if (value != <Keyword>)
        {
            RaiseEvent();
        }
        <Keyword> = value;
    }
}

A questão principal que tenho é que o uso de propriedades automáticas não permite a mesma flexibilidade na validação etc. que uma propriedade com um campo de apoio explícito o faz. No entanto, um campo de apoio explícito tem desvantagem em algumas situações de permitir a classe em que está contido para acessar o campo de apoio quando deve acessar e reutilizar a validação, alterar o rastreamento etc. da propriedade, como qualquer outra classe que possa estar acessando a propriedade externamente.

No exemplo acima, o acesso ao campo de apoio seria escopo para a propriedade, impedindo a contornar a validação da propriedade, rastreamento de alterações etc.

Editar: Eu mudei <campo de apoio> para <weenword>. Eu proporia uma nova palavra -chave semelhante ao valor. campo Faria muito bem, embora tenha certeza de que está sendo usado em muitos código existentes.

Foi útil?

Solução

Depois de ler seus comentários na resposta de Mehrdad, acho que entendo seu problema um pouco melhor.

Parece que você está preocupado com a capacidade do desenvolvedor de acessar o estado privado na classe que eles estão escrevendo, ignorando sua lógica de validação etc. Isso sugere que o estado não deve estar contido na classe.

Eu sugeriria a seguinte estratégia. Escreva uma classe genérica que represente um valor validado. Esta classe mantém apenas o valor de apoio e permite apenas acesso/mutação via métodos GET e Set. Um delegado é passado para o ValidatedValue para representar a lógica de validação:

public class ValidatedValue< T >
{
    private T m_val;
    public ValidationFn m_validationFn;

    public delegate bool ValidationFn( T fn );

    public ValidatedValue( ValidationFn validationFn )
    {
        m_validationFn = validationFn;
    }

    public T get()
    {
        return m_val;
    }

    public void set(T v)
    {
        if (m_validationFn(v))
        {
            m_val = v;
        }
    }
}

É claro que você pode adicionar mais delegados conforme necessário (por exemplo, para apoiar a notificação de alteração pré/pós).

Sua aula agora usaria o ValidatedValue no lugar de uma loja de apoio para sua propriedade.

O exemplo abaixo mostra uma classe, MyClass, com um número inteiro que é validado para ser menor que 100. Observe que a lógica para lançar uma exceção está na MyClass, não no ValidatedValue. Isso permite que você faça regras de validação complexas que dependem de outro estado contido no MyClass. A notação lambda foi usada para construir o delegado de validação - você poderia ter vinculado a uma função de membro.

public partial class MyClass
{
    private ValidatedValue<int> m_foo;

    public MyClass()
    {
        m_foo = new ValidatedValue<int>(
            v => 
            {
                if (v >= 100) RaiseError();
                return true;
            }
        );
    }

    private void RaiseError()
    {
        // Put your logic here....
        throw new NotImplementedException();
    }

    public int Foo
    {
        get { return m_foo.get(); }
        set { m_foo.set(value); }
    }
}

Espero que ajude - um pouco fora do tópico original, mas acho que é mais alinhado com suas preocupações reais. O que fizemos é retirar a lógica de validação da propriedade e colocá -la nos dados, que é exatamente onde você o queria.

Outras dicas

Não, não existe. Se você deseja acessar o campo de apoio, não use propriedades automáticas e role as suas próprias.

Concordo que seria ótimo ter um campo que só fosse acessível pela propriedade e não pelo resto da classe. Eu usaria isso o tempo todo.

Enquanto o Msdn estados:

"No C# 3.0 e posterior, as propriedades implementadas automaticamente tornam mais concisas de propriedade da propriedade quando nenhuma lógica adicional é necessária nos acessores de propriedades. Eles também permitem que o código do cliente crie objetos quando você declarar uma propriedade como mostrado no exemplo a seguir, o compilador Cria um campo de apoio privado e anônimo só pode ser acessado através dos acessores GET e Set da propriedade ".

Como você tem lógica adicional nos acessores, o uso de propriedades implementadas automaticamente não é apropriado em seu cenário.

Enquanto o campo de apoio existe, é dado um nome mutilado para impedi -lo de referência a ele facilmente - a ideia é que você Nunca faça referência ao campo diretamente. Por toda a conta dos interesses, você pode usar o refletor para desmontar seu código e descobrir o nome do campo, mas eu recomendaria que você não use o campo diretamente, pois esse nome pode realmente ser volátil, para que seu código possa quebrar a qualquer momento.

Não, mas você pode em uma subclasse:

public class Base
{
    public string Name
    {
        get;
        virtual set;
    }
}

public class Subclass : Base
{
    // FIXME Unsure as to the exact syntax.
    public string Name
    {
        override set
        {
            if (value != base.Name)
            {
                RaiseEvent();
            }

            base.Name = value;
        }
    }
}

Se você vai fazer isso, por que está usando propriedades automáticas?!

Uma propriedade simples fez isso de volta em 1.0. Eu não acho que faça sentido adicionar complexidade ao idioma para cada caso especial. Você precisa da propriedade para fazer modelo de armazenamento/recuperação simples ou precisa de mais do que isso. Neste último caso, uma propriedade normal servirá.

Você não pode fazer isso, tenho medo. Essa é uma das razões pelas quais comecei a escrever Brinquedos de energia moxaml, para fornecer a capacidade de converter propriedades automáticas em propriedades notificadas.

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