Quando você deve colocar o tipo de dados Chave / Valor em sua própria classe, em vez de usar uma estrutura genérica pré-criada, como a KeyValuePair
ou a Tuple
?
Por exemplo, a maioria das ComboBox que eu crie contém um DisplayName e um Value. Esse é o tipo de dados que estou tentando decidir quando colocar uma nova classe e quando usar apenas um KeyValuePair.
Atualmente, estou trabalhando em algo que usa iCalendar
, e os dados do usuário selecionado são combinados em um key1=value1;key2=value2;
tipo de string. Comecei colocando os dados em um KeyValuePair<string,string>
, mas agora estou me perguntando se deveria ser sua própria classe.
No geral, estou interessado em descobrir quais diretrizes são usadas ao decidir usar uma estrutura / classe existente como um KeyValuePair
objeto sobre duas propriedades e em que tipo de situações você usaria um sobre o outro.
fonte
tuple
tipo.iCalendar
e queria objetos paraBYDAY
eBYSETPOS
. Eles aparecem nas caixas de combinação, mas os dados reais são combinados na sequência de regras recorrente, que é umkey=value;
tipo de sequênciaRespostas:
Geralmente, eu usaria um objeto em vez de um KeyValuePair ou Tuple na maioria dos casos. Primeiro, quando você chega seis meses depois para fazer alterações, é muito mais fácil descobrir qual era sua intenção antes, em vez de se perguntar o que
Tuple t
é e por que ela tem esses valores engraçados. Segundo, à medida que as coisas crescem e mudam, você pode facilmente fornecer o comportamento simples dos objetos de transferência de dados, conforme necessário. Precisa ter dois formatos de nome? Fácil, basta adicionar sobrecargas ToString () apropriadas. Precisa implementar alguma interface? Sem problemas. Por fim, existe quase zero de sobrecarga na criação de um objeto simples, especialmente com propriedades automáticas e conclusão de código.Proteção de bônus: se você deseja impedir que esses objetos poluam seu espaço para nome, criar classes particulares dentro das classes é uma ótima maneira de manter as coisas em sigilo e evitar dependências estranhas.
fonte
A regra para definir uma nova classe é simples: é resumida em "Navalha de Occam".
http://c2.com/cgi/wiki?OccamsRazor
Não introduza novas classes sem uma boa razão. Ou use classes pré-criadas o máximo possível. Ou invente o mínimo possível. No entanto, você se sente à vontade para escrever menos código.
Você não pode usar uma classe pré-criada se precisar atribuir alguma responsabilidade exclusiva ao objeto e essa responsabilidade não estiver definida na classe pré-criada. Muitas vezes, este é um método único.
A
tuple
ouKeyValuePair
é preferido.Até.
Você precisa de algumas funcionalidades que não fazem parte de A
tuple
ouKeyValuePair
. Então você tem que definir sua própria classe.fonte
tuple
ouKeyValuePair
"? KeyValuePair pelo menos tem alguma forma limitada de semântica, mas as tuplas raramente têm (pode ser possível, dependendo do contexto) imho. A introdução de uma nova classe deve fornecer claramente uma semântica clara.Se você escreve sua própria classe, tem um lugar claro para colocar a documentação sobre quais são os dois valores. Especialmente porque duas strings não são uma definição muito clara. No entanto, você poderia escrever algo como
fonte
MyPair
define quais são os valores da Tupla e para que são usados.Item1
eItem2
! Não é tão fácil definir toda a classe?public class SideStrings { public string Left { get; set; } public string Right { get; set; } }
S.Lott escreveu
Deixe-me dizer por que tenho um problema sério com isso. Desde a
parece estar bem .... KeyValue [string, KeyValue [string, KeyValuePair [string, string]]] também está bem? Não sei o que S.Lott vai dizer sobre isso, mas meu chefe acha que está tudo bem.
Atrevo-me a discordar. E aqui está o porquê: Reduz a legibilidade do código a seguir. A função que preencherá essa estrutura de dados será muito mais complexa e sujeita a erros (err .. exceção) (imagine também pelo menos alguma lógica de negócios). Não discuti muito com meu chefe, mas vou dizer aqui: A legibilidade supera a economia de espaço em minutos (que era sua argumento ). Portanto, não seria um objeto de classe no qual existem alguns campos; mas alguns permanecem vazios às vezes melhor?
PS Eu sou um Ultra_Noob, por favor, diga-me se estou errado.
fonte
KeyValuePair<string,string>
é bom, assumindo que as coisas colocadas são de fato chaves e valores. Aqui, reutilizar uma classe existente é uma vitória, pois você salva o código de gravação e obtém interoperabilidade. OTOH, usar algo tão complicado quanto naKeyValuePair<string,KeyValuePair<string,string>>
maioria das vezes é complicado demais para ser prático. Às vezes, pode estar certo - quando você não precisa de funcionalidade adicional, quando o significado é óbvio e quando funciona bem com outras classes. YMMV, isso está apenas pesando os prós e contras.Quando dizemos par de chave / valor , geralmente penso em tabelas de hash ou matrizes associativas ou simplesmente em um objeto KeyValuePair . Eu uso todos eles e não há diferença em quando eu uso quais.
Eu acho que a coisa mais importante em uma lista de pares chave / valor é que, chaves devem ser únicas (já que é uma chave, afinal), e todas as estruturas acima mencionadas realmente me fornecem essa funcionalidade.
Fora isso, quero pesquisar por chaves ou executar ações no estilo de lista (matriz) como push e pop.
Portanto, minha resposta é NÃO e não crio objetos explicitamente para pares de chave / valor, pois muitas estruturas internas já fazem isso por mim.
fonte
O capítulo seis do Código Limpo tem uma boa descrição de quando usar uma estrutura de dados versus uma classe. Em poucas palavras, você usa uma estrutura de dados quando antecipa a adição de novas funções para operar com esses dados. Você usa uma classe quando antecipa a adição de novos tipos de dados a serem operados pelas funções existentes. Seu ComboBox é um exemplo deste último. Você tem um conjunto de funções (a implementação da ComboBox) operando em vários tipos de dados diferentes (diferentes tipos de dados para diferentes widgets).
fonte
Talvez eu concorde com Wilding aqui , mas também sou um pouco irritado com esse tipo de coisa.
Eu sugeriria que os tipos internos geralmente são objetos de mecanismo . KeyValuePair, por exemplo, faz parte do mecanismo de um dicionário e tabelas de hash, ajudando a garantir chaves únicas e elas possuem propriedades com nomes significativos no contexto do próprio mecanismo.
Por outro lado, o uso de objetos de dados personalizados fornece uma melhor representação dos seus dados e muitos benefícios, incluindo legibilidade e extensibilidade. Não há nada para parar de reutilizar o código existente em objetos personalizados, como sugerido pelo Sign , mas eu tentaria ocultar a classe agrupada e evitar vazamentos de abstração , para que você possa alterar a implementação subjacente posteriormente, sem afetar o restante do código. .
Então a verdadeira questão: você está representando dados ou está usando os dados em um mecanismo? (e eu não recomendaria misturar esses conceitos).
Na minha experiência, não há nada pior do que ver uma Tupla [string, string] sendo passada para um método e não ter uma maneira imediata de saber o que o Item1 e o Item2 devem ser. É melhor usar Tuplas dentro de métodos ou apenas como membros privados de uma classe.
fonte