Passare solo un tipo come parametro in C #


130

Ipoteticamente sarebbe utile per me fare questo:

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

dove il metodo GetColumns chiamerà un metodo diverso all'interno a seconda del tipo passato.

Sì, potrei farlo come una bandiera booleana o simile, mi chiedevo solo se ci fosse un modo per passare forse questo, e poi chiedere:

typeof (arg [1]) o simile ...

Potrei anche ignorare il metodo, usare generici, ecc. So che ci sono diversi modi per farlo, ero solo curioso se fosse possibile.


Il mio pensiero esattamente, a seconda di cosa sia effettivamente foo. foo.GetColumnValues<int>(dm.mainColumn)potrebbe essere la strada da percorrere.
Major Productions

1
Come ho detto, mi rendo conto che ci sono altri modi per farlo (flag booleano, generici, override del metodo) Mi chiedevo solo se fosse possibile come parametro.
Mark Mayo

@MarkMayo: Non capisco la domanda se "sai che potresti anche ignorare il metodo, usare generici, ecc. E sai che ci sono diversi modi per farlo, eri solo curioso se fosse possibile" . Quindi sai tutto questo ma sei curioso se è possibile ??
Tim Schmelter

@TimSchmelter - nella forma che descrivo. cioè passandolo come 2 ° parametro. A quanto pare, Reed ha detto quello che stavo cercando - dove usi (..., tipo di tipo). Questo è quello che stavo cercando.
Mark Mayo

1
Bella domanda, votata positivamente, vedo che MS usa Type come parametro per gli operatori incorporati in VB.NET, ad esempio trycast, e ho spesso desiderato di poterlo fare io stesso in C # / VB - nel modo che descrivi.
Chalky

Risposte:


213

Esistono due approcci comuni. Primo, puoi passareSystem.Type

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

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

Questo sarebbe chiamato come: int val = (int)GetColumnValue(columnName, typeof(int));

L'altra opzione sarebbe usare i generici:

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

Questo ha il vantaggio di evitare la boxe e fornire una certa sicurezza di tipo, e verrebbe chiamato come: int val = GetColumnValue<int>(columnName);


1
Puoi anche fare un metodo di estensione, public static T GetColumnValue <T> (questa stringa columnName) {...} quindi puoi dire foo.GetColumnValues ​​<string> (dm.mainColumn)
Joshua G

Ma come si definisce un metodo che ha più argomenti e uno di essi dovrebbe essere generico? Poiché il generico è definito prima dell'elenco degli argomenti del metodo, come fai a sapere quale dovrebbe essere un generico allora?
BadmintonCat

5
@BadmintonCat T Foo<T,U>(string arg1, U arg2)o simile
Reed Copsey,

Quando si utilizza il primo approccio, esiste un modo per assegnare un valore predefinito al tipo? (ad es. qualcosa del tipo object GetColumnValue(string columnName, Type type = object)? Non sembra funzionare per me, ma sarebbe utile saperlo.
Dave Cole,

22

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

In alternativa, potresti utilizzare un metodo generico:

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

e potresti quindi usarlo come:

foo.GetColumnValues<string>(dm.mainColumn);

13

Puoi passare un tipo come argomento, ma per farlo devi usare typeof:

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

Il metodo dovrebbe accettare un parametro con tipo Type.


dove il metodo GetColumns chiamerà un metodo diverso all'interno a seconda del tipo passato.

Se si desidera questo comportamento, non è necessario passare il tipo come argomento ma utilizzare invece un parametro di tipo.

foo.GetColumnValues<int>(dm.mainColumn)

8
foo.GetColumnValues(dm.mainColumn, typeof(int));
foo.GetColumnValues(dm.mainColumn, typeof(string));

O usando generici:

foo.GetColumnValues<int>(dm.mainColumn);
foo.GetColumnValues<string>(dm.mainColumn);

3
Non ti ho visto, ma probabilmente è perché stai mostrando come sarebbe stato chiamato e non hai specificato la definizione della funzione
JConstantine,

3
Odio quando le persone hanno bisogno di essere nutrite con il cucchiaio. La risposta + una lettura molto breve di MSDN è sufficiente. Ho il sospetto che i votanti verso il basso siano i rispondenti che competono con il rappresentante - che meschino.
Danny Varod

1

Puoi farlo, avvolgilo e basta typeof()

foo.GetColumnValues(typeof(int))

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


0

Usa tipi generici!

  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 chiamalo così:

  DataExtraction<AdPerformanceRow> extractor = new DataExtraction<AdPerformanceRow>(dates, predicates , cids);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.