Несколько параметров в списке в С#. Как создать без класса?

Это, вероятно, довольно очевидный вопрос, но как я могу создать List, который имеет несколько параметров без создания класса.

Пример:

var list = new List<string, int>();

list.Add("hello", 1);

Я обычно использовал бы такой класс:

public class MyClass
{
    public String myString {get; set;}
    public Int32 myInt32 {get; set;}
}

затем создайте свой список, выполнив следующие действия:

var list = new List<MyClass>();
list.Add(new MyClass { myString = "hello", myInt32 = 1 });

Ответ 1

Если вы используете .NET 4.0, вы можете использовать Tuple.

List<Tuple<T1, T2>> list;

Для более старых версий .NET вам необходимо создать собственный класс (если вам не повезло, чтобы найти класс, который соответствует вашим потребностям в библиотеке базового класса).

Ответ 2

Если вы не возражаете, что объекты, подлежащие вымыванию, вы можете использовать класс Tuple, добавленный в .net 4

var list = new List<Tuple<string,int>>();
list.Add(new Tuple<string,int>("hello", 1));

list[0].Item1 //Hello
list[0].Item2 //1

Однако, если вы каждый раз добавляете два элемента, а один из них - уникальный идентификатор, вы можете использовать Dictionary

Ответ 3

При необходимости вы можете использовать словарь, который также является общей коллекцией:

Dictionary<string, int> d = new Dictionary<string, int>();
d.Add("string", 1);

Ответ 4

Только список принимает только один параметр типа. Самое близкое, что вы получите в списке:

 var list = new List<Tuple<string, int>>();
 list.Add(Tuple.Create("hello", 1));

Ответ 5

Чтобы добавить к тому, что мне предложили, мне нравится следующая конструкция, чтобы избежать раздражения добавления членов в коллекции keyvaluepair.

public class KeyValuePairList<Tkey,TValue> : List<KeyValuePair<Tkey,TValue>>{
    public void Add(Tkey key, TValue value){
        base.Add(new KeyValuePair<Tkey, TValue>(key, value));
    }
}

Это означает, что конструктор может быть инициализирован с лучшим синтаксисом::

var myList = new KeyValuePairList<int,string>{{1,"one"},{2,"two"},{3,"three"}};

Мне лично нравится приведенный выше код над более подробными примерами. К сожалению, С# на самом деле не поддерживает типы кортежей изначально, поэтому этот маленький хак творит чудеса.

Если вам действительно нужно больше 2, я предлагаю создать абстракции по типу кортежа. (хотя Tuple - это класс, а не структура типа KeyValuePair, это интересное различие).

Как ни странно, синтаксис списка инициализаторов доступен на любом IEnumerable, и он позволяет использовать любой метод Add, даже те, которые на самом деле не перечислены вашим объектом. Это очень удобно, если вы хотите добавить элемент object[] в качестве члена params object[].

Ответ 6

Другое решение создает общий список анонимного типа.

 var list = new[]
 { 
    new { Number = 10, Name = "Smith" },
    new { Number = 10, Name = "John" } 
 }.ToList();

 foreach (var item in list)
 {
    Console.WriteLine(item.Name);
 }

Это также дает вам поддержку intellisense, я думаю, что в некоторых ситуациях это лучше, чем Tuple и Dictionary.

Ответ 7

Как сказал Скотт Чемберлен (и несколько других), Tuples работают лучше всего, если вы не против иметь неизменяемые объекты (то есть только для чтения).

Если, как и предложил Дэвид, вы хотите ссылаться на int на строковое значение, например, вы должны использовать словарь

Dictionary<string, int> d = new Dictionary<string, int>();
d.Add("string", 1);
Console.WriteLine(d["string"]);//prints 1

Если, однако, вы хотите с уверенностью хранить свои элементы в списке и не хотите использовать систему ссылок в стиле словаря, тогда ваш лучший выбор (то есть только реальное решение прямо сейчас) будет заключаться в использовании KeyValuePair, который по существу является std:: pair для С#:

var kvp=new KeyValuePair<int, string>(2, "a");
//kvp.Key=2 and a.Value="a";
kvp.Key = 3;//both key and
kvp.Value = "b";//value are mutable

Конечно, это стекируется, поэтому, если вам нужен большой кортеж (например, если вам нужны 4 элемента), вы просто складываете его. Предоставлено это очень быстро уродливо:

     var quad=new KeyValuePair<KeyValuePair<int,string>, KeyValuePair<int,string>>
                (new KeyValuePair<int,string>(3,"a"),
                new KeyValuePair<int,string>(4,"b"));
//quad.Key.Key=3

Таким образом, очевидно, что если вы должны это сделать, вы должны, вероятно, также определить вспомогательную функцию.

Мой совет: если ваш кортеж содержит более двух элементов, определите свой собственный класс. Вы можете использовать инструкцию typedef-esque, например:

using quad = KeyValuePair<KeyValuePair<int,string>, KeyValuePair<int,string>>;

но это не упрощает создание экземпляров. Вы, вероятно, потратили намного меньше времени на создание параметров шаблона и больше времени на не-шаблонный код, если вы идете с пользовательским классом при работе с кортежами из более чем 2 элементов.

Ответ 8

Для тех, кто хочет использовать класс.

Создайте класс со всеми необходимыми параметрами

Создайте список с классом как параметр

class MyClass
        {
            public string S1;
            public string S2;
        }

List<MyClass> MyList= new List<MyClass>();

Ответ 9

Это отлично работает со мной

List<string> myList = new List<string>();
myList.Add(string.Format("{0}|{1}","hello","1") ;


label:myList[0].split('|')[0] 
val:  myList[0].split('|')[1]