Передача только типа в качестве параметра в C #

130

Гипотетически мне было бы удобно это сделать:

foo.GetColumnValues(dm.mainColumn, int)
foo.GetColumnValues(dm.mainColumn, string)

где метод GetColumns будет вызывать другой метод внутри в зависимости от переданного типа.

Да, я мог бы сделать это как логический флаг или что-то подобное, я просто подумал, есть ли способ передать это, а затем спросить:

typeof (arg [1]) или подобное ...

Я также мог переопределить метод, использовать дженерики и т. Д. - Я знаю, что есть разные способы сделать это, мне просто было любопытно, возможно ли это.

Марк Мэйо
источник
Точно моя мысль, в зависимости от того, что такое foo на самом деле. foo.GetColumnValues<int>(dm.mainColumn)может быть путь.
Major Productions
1
Как я уже сказал, я понимаю, что есть другие способы сделать это (логический флаг, дженерики, переопределение метода). Мне просто интересно, возможно ли это в качестве параметра.
Марк Мэйо
@MarkMayo: Я не понимаю вопроса, если вы «знаете, что вы также можете переопределить метод, использовать дженерики и т. Д., И знаете, что есть разные способы сделать это, вам просто было любопытно, возможно ли это» . Значит, вы все это знаете, но вам интересно, возможно ли это ??
Тим Шмелтер
@TimSchmelter - в описанном мной виде. т.е. передача его как 2-й параметр. Как оказалось, Рид как бы сказал, что я искал - где вы используете (..., Type type). Это то, что я искал.
Марк Мэйо
1
Хороший вопрос, за него проголосовали, я вижу, как MS использует Type в качестве параметра для встроенных операторов в VB.NET, например, trycast, и мне часто хотелось сделать это сам на C # / VB - так, как вы описываете.
Chalky

Ответы:

213

Есть два общих подхода. Сначала вы можете пройтиSystem.Type

object GetColumnValue(string columnName, Type type)
{
    // Here, you can check specific types, as needed:

    if (type == typeof(int)) { // ...

Это будет называться так: int val = (int)GetColumnValue(columnName, typeof(int));

Другой вариант - использовать дженерики:

T GetColumnValue<T>(string columnName)
{
    // If you need the type, you can use typeof(T)...

Это имеет то преимущество, что позволяет избежать упаковки и обеспечить некоторую безопасность типов, и будет называться так: int val = GetColumnValue<int>(columnName);

Рид Копси
источник
1
Вы также можете использовать метод расширения, public static T GetColumnValue <T> (эта строка columnName) {...}, тогда вы можете сказать foo.GetColumnValues ​​<string> (dm.mainColumn)
Джошуа Дж.
Но как определить метод, который имеет несколько аргументов, и один из них должен быть универсальным? Так как универсальный параметр определяется перед списком аргументов метода, как узнать, какой из них должен быть универсальным?
BadmintonCat
5
@BadmintonCat T Foo<T,U>(string arg1, U arg2)или аналогичный
Рид Копси
При использовании первого подхода есть ли способ присвоить типу значение по умолчанию? (например, что-то вроде object GetColumnValue(string columnName, Type type = object)? Это не совсем подходит для меня, но было бы полезно знать.
Дэйв Коул
22

foo.GetColumnValues(dm.mainColumn, typeof(string))

В качестве альтернативы вы можете использовать общий метод:

public void GetColumnValues<T>(object mainColumn)
{
    GetColumnValues(mainColumn, typeof(T));
}

и затем вы могли бы использовать его так:

foo.GetColumnValues<string>(dm.mainColumn);
Питер Ричи
источник
13

Вы можете передать тип в качестве аргумента, но для этого вы должны использовать typeof:

foo.GetColumnValues(dm.mainColumn, typeof(int))

Метод должен принять параметр с типом Type.


где метод GetColumns будет вызывать другой метод внутри в зависимости от переданного типа.

Если вам нужно такое поведение, вам не следует передавать тип в качестве аргумента, а вместо этого использовать параметр типа.

foo.GetColumnValues<int>(dm.mainColumn)
Марк Байерс
источник
8
foo.GetColumnValues(dm.mainColumn, typeof(int));
foo.GetColumnValues(dm.mainColumn, typeof(string));

Или используя дженерики:

foo.GetColumnValues<int>(dm.mainColumn);
foo.GetColumnValues<string>(dm.mainColumn);
Дэнни Варод
источник
3
Я вас не двинул, но, вероятно, потому, что вы показываете, как он будет вызываться, и не указали определение функции
JConstantine
3
Ненавижу, когда людям нужно кормить с ложечки. Ответ + действительно краткое прочтение MSDN достаточно. Я подозреваю, что оппоненты - это респонденты, конкурирующие между собой - как мелко.
Дэнни Варод 08
1

Вы можете сделать это, просто заверните его в typeof()

foo.GetColumnValues(typeof(int))

public void GetColumnValues(Type type)
{
    //logic
}
Кевин ДиТраглия
источник
0

Вы можете использовать аргумент типа Type - iow, передать typeof (int). Вы также можете использовать дженерики для (возможно, более эффективного) подхода.

внутренняя ошибка сервера 500
источник
0

Используйте универсальные типы!

  class DataExtraction<T>
{
    DateRangeReport dateRange;
    List<Predicate> predicates;
    List<string> cids;

    public DataExtraction( DateRangeReport dateRange,
                           List<Predicate> predicates,
                           List<string> cids)            

    {
        this.dateRange = dateRange;
        this.predicates = predicates;
        this.cids = cids;
    }
}

И назовите это так:

  DataExtraction<AdPerformanceRow> extractor = new DataExtraction<AdPerformanceRow>(dates, predicates , cids);
Борис Детрий
источник