Utilizando as Interfaces explícitas para impedir a modificação acidental de propriedades em C #
-
19-09-2019 - |
Pergunta
Eu tropecei em um recurso de resolução # método C que eu não percebi antes. Ou seja, quando eu explicitamente implementar uma interface que suporta um setter, ea interface implícito só oferece um conjunto protegido, o compilador sensatamente remete para o conjunto protegido quando eu chamá-lo. Então eu fico a maior parte da conveniência de propriedades implementadas automaticamente, mas posso impedir a modificação acidental de campos por clientes que não deve ser alterá-los.
Como exemplo,
virtual public DateTime CreatedOn { get; protected set; }
virtual public DateTime? ModifiedOn { get; protected set; }
#region IHaveUpdateDateFields Members
DateTime IHaveUpdateDateFields.CreatedOn
{
get
{
return this.CreatedOn;
}
set
{
this.CreatedOn = value;
}
}
DateTime? IHaveUpdateDateFields.ModifiedOn
{
get
{
return this.ModifiedOn;
}
set
{
this.ModifiedOn = value;
}
}
Então meu modelo de código ligação não acidentalmente definir a data, mas meu ORM evento ouvinte pode verificar a existência de entidades que implementam IHaveUpdateDateFields e definir a data em que persiste a minha entidade.
As minhas perguntas são:
- Am I contando com comportamento definido, ou estou garantido que todos C # compiladores irá resolver métodos desta maneira? Eu não quero para descobrir que o C # padrão diz que este tipo de resolução método é indefinido e, em seguida, acidentalmente obter um estouro de pilha horrível quando eu construir para Mono, por exemplo.
- Existe uma agradável (idealmente terser) maneira de fazer isso? Eu poderia ter uma interface ModelBinder-safe que eu passar para o meu controlador, mas isso não parece que ele iria me salvar código e eu não acho que isso iria fornecer o mais transparente uma abordagem de minimizar modificação acidental de propriedades.
Solução
Isso é perfeitamente bem definida; as implementações de interfaces explícitas têm prioridade quando se utiliza a interface, ea propriedade regular leva efeito de outra forma (incluindo de dentro do corpo do get / set).
Como para torná-lo mais arrumado ... o melhor que posso oferecer é reformatá-lo para torná-lo menos extenso ...
DateTime IHaveUpdateDateFields.CreatedOn
{
get { return CreatedOn; }
set { CreatedOn = value; }
}
(note-se também que o this
é implícita e redundante)
Como um aparte - a segurança é apenas uma conveniência, e não uma garantia ... chamadores externos ainda pode usar o seu interface, e geralmente pode (ab) uso de reflexão para saltar últimos meras coisas como protected
- ou mesmo apenas definir os campos diretamente.