Передача просто типу в якості параметра в C #


130

Гіпотетично мені було б зручно це зробити:

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

де метод GetColumns буде викликати інший метод всередині залежно від типу, що передається.

Так, я міг би зробити це як булевий прапор чи подібне, я просто задумався, чи є спосіб, можливо, пропустити це, а потім запитати:

typeof (arg [1]) або подібне ...

Я також міг би перекрити метод, використовувати дженерики тощо - я знаю, що існують різні способи зробити це, мені було просто цікаво, якщо це можливо.


Моя думка саме, залежно від того, що таке foo насправді. foo.GetColumnValues<int>(dm.mainColumn)може бути шлях.
Основні постановки

1
Як я вже говорив, я розумію, що існують інші способи зробити це (булева прапор, генерика, перекриття методу), я просто задумався, чи можливо це як параметр.
Марк Майо

@MarkMayo: Я не розумію питання, якщо ви "знаєте, що ви також можете змінити метод, використовувати дженерики тощо", і знаєте, що для цього є різні способи, вам просто цікаво, чи це можливо " . Ви знаєте все це, але вам цікаво, чи можливо ??
Тім Шмелтер

@TimSchmelter - у формі, яку я описую. тобто передаючи його як 2-й параметр. Як виявляється, Рід якось сказав, що я був після - де ви використовуєте (..., Тип типу). Ось що я шукав.
Марк Майо

1
Хороший запитання, підкреслений, я бачу MS, що використовує Type як параметр для вбудованих операторів у VB.NET, наприклад, пробний, і часто хотів, щоб я міг це зробити сам у C # / VB - у моді, яку ви описуєте.
Крейда

Відповіді:


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
Ви також можете зробити метод розширення, загальнодоступний статичний T GetColumnValue <T> (цей рядок-ім'я) {...}, тоді ви можете сказати foo.GetColumnValues ​​<string> (dm.mainColumn)
Джошуа G

Але як ви визначаєте метод, який має кілька аргументів, і один з них повинен бути загальним? Оскільки загальний визначається перед списком аргументів методу, то як ви знаєте, який із них повинен бути загальним?
BadmintonCat

5
@BadmintonCat T Foo<T,U>(string arg1, U arg2)або подібне
Reed Copsey

При використанні першого підходу, чи є спосіб призначити типове значення за замовчуванням? (наприклад, щось на кшталт 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
Я тебе не записував, але це, мабуть, тому, що ти
показуєш,

3
Я ненавиджу це, коли людям потрібно годувати ложкою. Відповіді + дійсно коротке прочитання MSDN достатньо. Я підозрюю, що тих, хто втратив чинність, є відповідальні люди, котрі змагаються за репутацію.
Danny Varod

1

Ви можете це зробити, просто загорнувши його typeof()

foo.GetColumnValues(typeof(int))

public void GetColumnValues(Type type)
{
    //logic
}


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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.