#c# #list #generics
#c# #Список #общие
Вопрос:
Привет, у меня простая проблема с приложением sql, которую я, похоже, не способен решить. Это предполагает использование дженериков, с которыми я не слишком знаком. Я проводил исследования здесь и в Интернете, но, похоже, я не нашел подходящего решения для своего случая.
У меня есть два класса: таблица и поле. Я хочу, чтобы таблица содержала список полей, и я хочу, чтобы каждое поле содержало список набора записей. Сложная часть заключается в том, что я хочу, чтобы пользователь выбирал, какой тип набора записей реализовать.
Определение класса Table является:
namespace DBlib
{
public class DBTable<T>
{
public List<DBField<T>> FieldName = new List<DBField<T>>();
public DBTable (string NameOfTable)
{
}
public void AddField (string Name)
{
DBField<T> TempList = new DBField<T>();
FieldName.Add(TempList);
}
}
}
Определение класса поля является:
namespace DBlib
{
public class DBField<T>
{
public List<T> RecordSet = new List<T>();
public DBField()
{
}
}
}
С помощью этого кода пользователь вынужден приводить тип при создании экземпляра DBTable. Это неверно. Я хочу, чтобы пользователь приводил тип при вызове метода AddField. Можете ли вы предложить простой способ решения этой проблемы?
ОБНОВЛЕНИЕ # 1 Я изменил tempList как DBField в определении класса таблицы. Извините за возникшую путаницу.
Я хочу также добавить этот код, чтобы лучше объяснить, в чем моя проблема. Предполагая, что первое поле таблицы является целым числом, пользователь должен выполнить:
namespace SpecifytheName
{
public class User
{
DBTable<int> Table = new DBTable<int>();
public User()
{
}
}
}
Вместо этого я хочу, чтобы пользователь делал:
namespace SpecifytheName
{
public class User
{
DBTable Table1 = new DBTable("Table1");
// SPECIFY THE TYPE OF FIELD1 ONLY AT THIS POINT
Table1.AddField<int>("Field1"); //or something like this
public User()
{
}
}
}
Комментарии:
1.
TempList
должно быть типаList<DBField<T>>
, чтобы вышеприведенное работало в любом случае, не так ли2. Но как именно пользователь должен указывать (во время выполнения?) что тип должен быть «int» (или «double» или что-то еще?)
3. Что я считаю наиболее важным на данный момент, не зная больше подробностей о том, что вы на самом деле пытаетесь сделать, так это почему вы не используете стандартные типы данных, связанные с работой с SQL?
4. Похоже, он пытается изобрести велосипед
5. Что вам нужно понять о C # generics, так это то, что часть программы, закодированная для общих типов (класс или метод), не должна знать тип во время компиляции (я здесь чрезмерно упрощаю). НО где-то во время компиляции часть программы, которая ИСПОЛЬЗУЕТ эти классы или методы, должна указывать тип. Это не то, что можно извлечь из воздуха во время выполнения.
Ответ №1:
Я бы вообще решил эту проблему, используя не универсальный интерфейс для хранения ваших полей.
Итак, начните с этого интерфейса:
public interface IDBField
{
IList RecordSet { get; }
Type FieldType { get; }
}
Теперь реализуйте DBField<T>
так:
public class DBField<T> : IDBField
{
public List<T> RecordSet = new List<T>();
IList IDBField.RecordSet
{
get
{
return this.RecordSet;
}
}
Type IDBField.FieldType
{
get
{
return typeof(T);
}
}
}
Затем вы можете реализовать DBTable
следующим образом:
public class DBTable
{
public List<IDBField> FieldName = new List<IDBField>();
public void AddField<F>(string Name)
{
FieldName.Add(new DBField<F>());
}
}
Вы можете использовать FieldType
свойство on IDBField
для определения типа поля, а затем использовать отражение по мере необходимости, чтобы использовать значения RecordSet
соответствующим образом.
Комментарии:
1. Разве чего-то не хватает в том, как используется имя поля?
2. @Enigmativity Привет, спасибо. это именно то, что я искал, и я голосую за это как за ответ, который решает проблему. Еще раз спасибо!
3. @RenniePet — Да, есть, но этого тоже не хватало в вопросе, поэтому я его не учел.
Ответ №2:
Единственный способ, которым я могу видеть, что это работает, — это не использовать Generics, а просто использовать Object
класс.
например:
public class DBTable
{
public List<DBField<Object>> FieldName = new List<DBField<Object>>();
public DBTable (string NameOfTable)
{
}
public void AddField(string Name)
{
List<DBField<Object>> TempList = new List<DBField<Object>>();
FieldName.Add(TempList);
}
}
Это будет означать, что вы можете использовать любой тип в RecordSet
объекте, не ограничивая тип в классе DBTable.
Я мог бы немного ошибиться здесь, поскольку я не уверен, чего вы пытаетесь достичь, например, вы ничего не делаете с Name
параметром, переданным в AddField
метод, и ваш TempList
объект не того же типа, что и, FieldName
поэтому он должен вызывать некоторые ошибки..
Редактировать:
Я думаю, что я более четко понимаю, что вы пытаетесь сделать, попробуйте это —
public class DBTable
{
public List<DBField<Object>> FieldName = new List<DBField<Object>>();
public DBTable (string NameOfTable)
{
}
public void AddField<FieldType>(string Name)
{
DBField<FieldType> field = new DBField<FieldType>(Name);
FieldName.Add(field);
}
}
Таким образом, каждое поле (столбец) по-прежнему принудительно привязывается к типу, но DBTable не привязан к тому же типу.
Комментарии:
1. В этом случае, вероятно, было бы проще использовать неровный массив, а не по-прежнему создавать
DBField
как универсальный с типомObject
2. Я понимаю, чего вы пытаетесь достичь своим ответом, но я не верю, что OP имеет четкое представление о дженериках и о том, как они работают и функционируют в C #.
3. Он упомянул об этом в своем посте. Я думаю, что более конкретно нам нужно знать, чего он пытается достичь, независимо от использования его дженериков.
4. @LeonNewswanger Да, у меня пока нет четкого представления о том, как работают дженерики. Я читаю и кодирую (и делаю ошибки), пытаясь их изучить. В общем, я пытаюсь создать простую пользовательскую библиотеку, которая работает с базой данных. Я хочу, чтобы библиотека предоставляла пользователю объект с именем Table и объект с именем Field. В поле объекта у меня будет набор записей, который можно очистить и использовать для сохранения данных после оператора SELECT или для сбора данных для ВСТАВКИ или ОБНОВЛЕНИЯ. Что-то простое, чтобы мои ноги промокли. Спасибо за вашу помощь!
5. @LuckyLuke Тогда вы действительно пытаетесь изобрести велосипед. Отличные библиотеки для работы с SQL уже существуют. Если вы хотите узнать, как правильно использовать generics, вам следует начать с чего-то немного более простого.