Patrick Skelton Ответов: 3

Как получить универсальный тип в качестве поля кортежа?


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

List<Tuple<string,List<T>>> listOfTuples = null;

void InitialiseList()
{
    listOfTuples = new ...
    listOfTuples.Add( new ... );
    ...
}


Что я уже пробовал:

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

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

Кстати, я нахожусь на C#6.

3 Ответов

Рейтинг:
23

Graeme_Grant

Я думаю, что это то, что вы пытаетесь сделать:

Tuple<string, List<T>> TupleFactory<T>(string value, List<T> values)
{
    return new Tuple<string, List<T>>(value, values);
}

Использовать:
var listOfTuples1 = TupleFactory("test value", new List<string>
    {
        "test value 1",
        "test value 2",
        "test value 3",
        "test value 4",
    });

var listOfTuples2 = TupleFactory("test value", new List<int> { 1, 2, 3, 4 });


Рейтинг:
19

F-ES Sitecore

Вы можете попробовать использовать наследование, но Решение 1, вероятно, лучше, если его можно использовать

public class MyData<T> : List<Tuple<string, List<T>>>
{

}


MyData<string> dataA = new MyData<string>();

dataA.Add(new Tuple<string, List<string>>("String 1", new List<string> { "A", "B", "C" }));
dataA.Add(new Tuple<string, List<string>>("String 2", new List<string> { "X", "Y", "Z" }));


MyData<int> dataB = new MyData<int>();

dataB.Add(new Tuple<string, List<int>>("Int 1", new List<int> { 1, 2, 3 }));
dataB.Add(new Tuple<string, List<int>>("Int 2", new List<int> { 4, 5, 6 }));


Patrick Skelton

На самом деле, я думаю, что это подчеркивает, где мое мышление мутно. Я не могу использовать этот код, потому что каждый Кортеж, который я добавляю, имеет другой параметр типа. Тем не менее, все типы имеют общий базовый класс, но я все еще не могу убедить компилятор увидеть мою сторону вещей.

F-ES Sitecore

Что-то вроде

публичный абстрактный класс животное
{
public string Name { get; set; }
}

общественный класс кошка: животное
{
}

собака общественного класса: животное
{
}

Список<Кортеж&ЛТ;строку, список<животное&ГТ;&ГТ;&ГТ; х = новый список<Кортеж&ЛТ;строку, список<животное&ГТ;&ГТ;&ГТ;();

List & lt;animal & gt; cats = новый список & lt;animal>();
кошки.Добавить (new Cat { Name = " Tiddles" });

Список<животное&ГТ; собаки = новый список<животное&ГТ;();
собаки.Добавить (новая собака { имя = " пятно" });

х.Добавить(новый Кортеж в<строка, список<животное&ГТ;&ГТ;("список 1", кошки));
х.Добавить(новый Кортеж в<строка, список<животное&ГТ;&ГТ;("Список 2", животные));

Patrick Skelton

Это странно. У меня действительно было что-то близкое к вашему коду, хотя я создал специальный частный класс для хранения элементов вместо использования кортежей. Очевидно, я делаю что-то другое, потому что получаю ошибку компилятора, когда пытаюсь добавить элемент в словарь, говоря, что производный класс не может быть преобразован в базовый класс.

частный класс BusinessObjectCacheItem< t & gt; где T : BusinessObjectBase
{
общественные BusinessObjectCacheItem( список<Т> businessObjectList, DataCommunicator в<Т> dataCommunicator )
{
_businessObjectList = businessObjectList;
_dataCommunicator = dataCommunicator;
}

public List< t & gt; BusinessObjectList { get { return _businessObjectList; } }
public DataCommunicator< t & gt; DataCommunicator { get { return _dataCommunicator; } }

частный список< t & gt; _businessObjectList = null;
private DataCommunicator< t & gt; _dataCommunicator = null;

}

частный словарь< BusinessObjectName,BusinessObjectCacheItem< businessobjectbase> & gt; _cacheItems = null;

частный недействительными InitialiseCacheItems()
{
_cacheItems = новый словарь & lt;BusinessObjectName, BusinessObjectCacheItem< businessobjectbase>>();
_cacheItems.Добавить (BusinessObjectName.Contact, new BusinessObjectCacheItem<businessobjectbase> ( _contactMasterList, _contactDataReaderWriter ) );
_cacheItems.Добавить (BusinessObjectName.Contact, new BusinessObjectCacheItem & lt;contact> ( _contactMasterList, _contactDataReaderWriter ) );
// Ни одна из последних двух строк не будет компилироваться, даже если Contact является производным от BusinessObjectBase.
}

Рейтинг:
0

johannesnestler

Мне интересно, почему никто не сказал очевидного - зачем вы возитесь с кортежами для таких случаев? Они не предназначены для "сложных случаев", просто создайте тип для хранения вашей информации и составьте список этого типа....
только мой 2С


Patrick Skelton

Я действительно упомянул в своем вопросе, что это может быть правильный путь. Код будет более читабельным.

Спасибо за ответ.

johannesnestler

СРИ, кажется, я его перечитал. так что все хорошо ;)

Graeme_Grant

Вопрос был не в этом, Но да, кортежи-не мой первый выбор.