Coleções são um conceito importante em POO, e o suporte total a coleções em C# é um dos melhores da linguagem.
Por que usar conjuntos genéricos? Antes do C# 2.0, as coleções podiam ser implementadas de duas maneiras principais: a. Uso do ArrayList Colocar objetos diretamente na ArrayList é intuitivo, mas como os itens na coleção são do tipo Objecto, você precisa fazer uma conversão de tipos tediosa toda vez que usa. b. Usar classes de coleção personalizadas Uma prática comum é herdar uma classe personalizada da classe abstrata CollectionBase e implementar uma coleção de tipos forte encapsulando o objeto IList. Esse método exige escrever uma classe personalizada correspondente para cada tipo de coleção, o que dá muito trabalho. O surgimento de coleções genéricas resolve bem os problemas acima, e apenas uma linha de código pode ser usada para criar um conjunto de um tipo especificado. O que é genérico? Genéricos são novos elementos em C# 2.0 (chamados de templates em C++) que são usados principalmente para resolver uma série de problemas semelhantes. Esse mecanismo permite que o nome da classe seja passado como argumento para o tipo genérico e o objeto correspondente seja gerado. Pode ser melhor pensar nos genéricos (incluindo classes, interfaces, métodos, delegados, etc.) como modelos, onde a parte variante é substituída pelo nome da classe passado como argumento, resultando em uma nova definição de tipo. Genérico é um tema relativamente amplo, e não vou analisá-lo em detalhes aqui, e quem tiver interesse pode consultar as informações relevantes. Como faço para criar uma coleção genérica? A classe genérica List sob o namespace System.Collections.Generic <T>é usada para criar coleções, e a sintaxe é a seguinte: [mw_shl_code=csharp,verdade] <T> ListaListaOfT = nova Lista<T>(); [/mw_shl_code] O "T" é o tipo a ser usado, que pode ser de tipos simples, como string, int ou tipos definidos pelo usuário. Vamos olhar um exemplo específico.
A classe Pessoa é definida da seguinte forma: [mw_shl_code=csharp,true] classe Pessoa
{ _name de corda privada; Nome _age de inteligência privada; Idade
Criar um objeto Pessoa Pessoa pública (nome da cadeia, int Idade) { this._name= Nome; this._age = Idade; }
Nome Nome da corda pública { get { return _name; } }
Idade public int Age { get { return _age; } }
}
//创建Person对象 Pessoa p1 = nova Pessoa ("Zhang San", 30); Pessoa p2 = nova pessoa ("Li Si", 20); Pessoa p3 = nova Pessoa ("Wang Wu", 50);
//创建类型为Person的对象集合 Pessoas da lista<Person> = nova Lista<Person>();
//将Person对象放入集合 pessoas. Add(p1); pessoas. Add(p2); pessoas. Add(p3);
//输出第2个人的姓名 Console.Write(persons[1]. Nome); [/mw_shl_code] Como você pode ver, coleções genéricas simplificam muito o código de implementação das coleções, permitindo criar facilmente coleções de tipos específicos. Além disso, coleções genéricas também oferecem funções mais poderosas, vamos dar uma olhada na ordenação e busca nelas. Ordenação de coleções genéricas A ordenação é baseada em comparação, e para ordenar, você deve primeiro comparar. Por exemplo, se houver dois números 1 e 2, para ordená-los, devemos primeiro comparar esses dois números e ordená-los de acordo com os resultados da comparação. Se você quiser comparar objetos, a situação é um pouco mais complicada, por exemplo, se você comparar objetos Pessoa, pode comparar por nome ou idade, o que exige determinar as regras de comparação. Um objeto pode ter múltiplas regras de comparação, mas apenas uma regra padrão, que é colocada na classe que define o objeto. As regras padrão de comparação são definidas no método CompareTo, que pertence à <T>interface genérica IComparable. Veja o código abaixo: [mw_shl_code=csharp,true]classe Pessoa :IComparável<Person>
{ Compare por idade public int CompareTo(Person p) { Devolva isso. Idade - p.Idade; } }[/mw_shl_code] Os parâmetros do método CompareTo são outro objeto do mesmo tipo para ser comparado, o valor de retorno é do tipo int; se o valor de retorno for maior que 0, significa que o primeiro objeto é maior que o segundo; se o valor de retorno for menor que 0, significa que o primeiro objeto é menor que o segundo; e se devolver 0, os dois objetos são iguais. Após definir as regras padrão de comparação, você pode ordenar a coleção usando o método Sort sem parâmetros, da seguinte forma: [mw_shl_code=csharp,true]// Ordenar a coleção de acordo com as regras padrão pessoas. Sort();
//输出所有人姓名 foreach (Pessoa p em pessoas)
{ Console.WriteLine(p.Name); A ordem de saída é "Li Si", "Zhang San" e "Wang Wu" }[/mw_shl_code] Na prática, muitas vezes é necessário ordenar a coleção de acordo com uma variedade de regras diferentes, o que requer a definição de outras regras de comparação, que podem ser definidas no método Comparar, que pertence à <T>interface genérica do IComparer; por favor, veja o seguinte código: [mw_shl_code=csharp,true]classe Comparador de NomeComparador : IComparer<Person>
{ Instâncias de sequenciadores de armazenamento NameComparer Default estático público = novo NameComparer();
Compare por nome int público Compare(Pessoa p1, Pessoa p2) { return System.Collections.Comparer.Default.Compare(p1. Nome, p2. Nome); } }[/mw_shl_code] Os parâmetros do método Compare são dois objetos do mesmo tipo a serem comparados, e o valor de retorno é do tipo int, e as regras de processamento de valor de retorno são as mesmas do método CompareTo. Comparer.Default retorna um objeto Comparer embutido para comparar dois objetos do mesmo tipo. Veja como ordenar a coleção com este comparador recém-definido: [mw_shl_code=csharp,true]//Ordenar a coleção por nome pessoas. Sort(NameComparer.Default);
//输出所有人姓名 foreach (Pessoa p em pessoas)
{ Console.WriteLine(p.Name); A ordem de saída é "Li Si", "Wang Wu" e "Zhang San" }[/mw_shl_code] Você também pode ordenar a coleção delegando, primeiro, definir um método para o delegado chamar e armazenar as regras de comparação, e pode usar um método estático. Veja o código abaixo: [mw_shl_code=csharp,true]classe ComparaçãoPessoaPessoa
{ Compare por nome public static int Nome(Pessoa p1, Pessoa p2) { return System.Collections.Comparer.Default.Compare(p1. Nome, p2. Nome); } }[/mw_shl_code] Os parâmetros do método são dois objetos do mesmo tipo a serem comparados, o valor de retorno é do tipo int, e a regra de processamento de valor de retorno é a mesma do método CompareTo.Depois, ordenar a coleção via o Sistema Genérico de Delegados embutido. <T>Comparação: [mw_shl_code=csharp,verdade] <Person> System.ComparisonNameComparison = novo System.Comparison<Person>(PersonComparison.Name); pessoas. Sort(NameComparison);
//输出所有人姓名 foreach (Pessoa p em pessoas)
{ Console.WriteLine(p.Name); A ordem de saída é "Li Si", "Wang Wu" e "Zhang San" }[/mw_shl_code] Pode-se ver que os dois últimos métodos podem ordenar a coleção de acordo com as regras especificadas, mas o autor prefere usar o método de delegação e pode considerar colocar várias regras de comparação em uma classe e depois chamá-las de forma flexível. Procure por coleções genéricas A busca é encontrar itens que atendam a condições específicas da coleção, e múltiplas condições de busca podem ser definidas e chamadas conforme necessário. Primeiro, defina os critérios de busca da seguinte forma: [mw_shl_code=csharp,true]classe PessoaPredicado
{ Encontre pessoas de meia-idade (acima de 40 anos) bool estático público Meia-Idade (Pessoa p) { se (p.Idade >= 40) retorno verdadeiro; senão retorne falso; } }[/mw_shl_code] Os critérios de busca acima são colocados em um método estático com um tipo de retorno booleano, e itens na coleção que atendem a certas condições retornam verdadeiro, ou contrário falso.Depois, pesquise na coleção via o sistema genérico de delegado embutido. Predicado<T>: [mw_shl_code=csharp,verdade] System.Predicate<Person> MidAgePredicate = novo <Person>System.Predicate(PersonPredicate.MidAge); Lista<Person> Pessoas de meia-idade = pessoas. FindAll (MidAgePredicate);
//输出所有的中年人姓名 foreach (Pessoa p em MidAgePersons)
{ Console.WriteLine(p.Name); Saída "Wang Wu" }[/mw_shl_code] Extensão de coleções genéricas E se você quiser pegar os nomes de todas as pessoas do conjunto, separados por uma vírgula? Considerando que a funcionalidade que uma única classe pode fornecer é limitada, é natural pensar <T>em estender a classe List, que também é uma classe e, portanto, pode ser estendida por herança. Veja o código abaixo: [mw_shl_code=csharp,true]// Defina a classe de coleção Persons Classe Pessoas: Lista<Person>
{ Obtenha os nomes de todos na coleção string pública GetAllNames() { se (isso. Contagem == 0) retorno "";
string val = ""; foreach (Pessoa p nisso) { val += p.Name + ","; }
Devolva Val. Substring(0, val. Comprimento - 1); }
}
//创建并填充Persons集合 Pessoas PersonCol = novas pessoas(); PessoaCol.Add(p1); PessoaCol.Add(p2); PessoaCol.Add(p3);
//输出所有人姓名 Console.Write(PessoaCol.RecebeTodosNomes()); Saída "Zhang San, Li Si, Wang Wu"[/mw_shl_code] Resumo: Este artigo foca no uso de genéricos em C# 2.0 para implementar coleções, bem como para estender a função de coleção, e o uso adequado de coleções genéricas pode reduzir muita duplicação de trabalho e melhorar significativamente a eficiência do desenvolvimento. Na verdade, conjuntos são apenas uma aplicação típica de genéricos, e se você quiser saber mais sobre genéricos, pode consultar outros materiais relevantes. Espero que este artigo tenha sido útil para você :-)
|