Passando apenas um tipo como parâmetro em C #

130

Hipoteticamente, seria útil para mim fazer isso:

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

onde o método GetColumns chamará um método diferente dentro, dependendo do tipo passado.

Sim, eu poderia fazê-lo como uma bandeira booleana ou similar, apenas me perguntava se havia uma maneira de talvez passar por isso e depois perguntar:

typeof (arg [1]) ou similar ...

Eu também poderia substituir o método, usar genéricos, etc. - eu sei que existem diferentes maneiras de fazer isso, fiquei curioso para saber se isso era possível.

Mark Mayo
fonte
Meu pensamento exatamente, dependendo do que foo realmente é. foo.GetColumnValues<int>(dm.mainColumn)pode ser o caminho a percorrer.
Major Productions
1
Como eu disse, percebo que existem outras maneiras de fazer isso (sinalizador booleano, genéricos, substituindo o método). Apenas me perguntei se isso era possível como parâmetro.
Mark Mayo
@ MarkMayo: Eu não entendo a pergunta se você "sabe que também pode substituir o método, usar genéricos, etc, e sabe que existem diferentes maneiras de fazer isso, estava curioso para saber se isso era possível" . Então você sabe tudo isso, mas está curioso para saber se é possível?
Tim Schmelter
@ TimSchmelter - na forma que eu descrevo. ou seja, passá-lo como o 2º parâmetro. Acontece que Reed disse o que eu estava procurando - onde você usa (..., tipo Type). Era isso que eu estava procurando.
Mark Mayo
1
Boa pergunta, com votos positivos, vejo o MS usando Type como parâmetro para operadores internos no VB.NET, por exemplo, trycast, e sempre desejei poder fazer isso sozinho em C # / VB - da maneira que você descreve.
Chalky

Respostas:

213

Existem duas abordagens comuns. Primeiro, você pode passarSystem.Type

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

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

Isso seria chamado como: int val = (int)GetColumnValue(columnName, typeof(int));

A outra opção seria usar genéricos:

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

Isso tem a vantagem de evitar o boxe e fornecer algum tipo de segurança, e seria chamado como: int val = GetColumnValue<int>(columnName);

Reed Copsey
fonte
1
Você também pode fazer um método de extensão, estático público T GetColumnValue <T> (esta string columnName) {...} e, em seguida, você pode dizer foo.GetColumnValues ​​<string> (dm.mainColumn)
Joshua G
Mas como você define um método que possui vários argumentos e um deles deve ser genérico? Como o genérico é definido antes da lista de argumentos do método, como você sabe qual deve ser um genérico?
BadmintonCat
5
@BadmintonCat T Foo<T,U>(string arg1, U arg2)ou semelhante
Reed Copsey
Ao usar a primeira abordagem, existe uma maneira de atribuir um valor padrão ao tipo? (por exemplo, algo como object GetColumnValue(string columnName, Type type = object)? Isso não parece ser bastante a trabalhar para mim, mas seria útil saber.
Dave Cole
22

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

Como alternativa, você pode usar um método genérico:

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

e você poderia usá-lo como:

foo.GetColumnValues<string>(dm.mainColumn);
Peter Ritchie
fonte
13

Você pode passar um tipo como argumento, mas para fazer isso, você deve usar typeof:

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

O método teria de aceitar um parâmetro com o tipo Type.


onde o método GetColumns chamará um método diferente dentro, dependendo do tipo passado.

Se você deseja esse comportamento, não deve passar o tipo como argumento, mas sim usar um parâmetro de tipo.

foo.GetColumnValues<int>(dm.mainColumn)
Mark Byers
fonte
8
foo.GetColumnValues(dm.mainColumn, typeof(int));
foo.GetColumnValues(dm.mainColumn, typeof(string));

Ou usando genéricos:

foo.GetColumnValues<int>(dm.mainColumn);
foo.GetColumnValues<string>(dm.mainColumn);
Danny Varod
fonte
3
Eu não dv você, mas foi provavelmente porque você está mostrando como ele seria chamado e não especificou a definição da função
JConstantine
3
Eu odeio quando as pessoas precisam de alimentação com colher. A resposta + uma leitura realmente breve do MSDN é suficiente. Suspeito que os que votam para baixo são respondedores competindo com rep - que mesquinho.
precisa
1

Você pode fazer isso, apenas envolva-o typeof()

foo.GetColumnValues(typeof(int))

public void GetColumnValues(Type type)
{
    //logic
}
Kevin DiTraglia
fonte
0

Você pode usar um argumento do tipo Type - iow, pass typeof (int). Você também pode usar genéricos para uma abordagem (provavelmente mais eficiente).

500 - Erro interno do servidor
fonte
0

Use tipos genéricos!

  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;
    }
}

E chame assim:

  DataExtraction<AdPerformanceRow> extractor = new DataExtraction<AdPerformanceRow>(dates, predicates , cids);
Boris Detry
fonte