Pasar solo un tipo como parámetro en C #

130

Hipotéticamente sería útil para mí hacer esto:

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

donde el método GetColumns llamará a un método diferente dentro dependiendo del tipo pasado.

Sí, podría hacerlo como una bandera booleana o similar, solo me preguntaba si había una forma de pasar esto, y luego preguntar:

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

También podría anular el método, usar genéricos, etc. Sé que hay diferentes formas de hacerlo, tenía curiosidad por saber si esto era posible.

Mark Mayo
fuente
Mi pensamiento exactamente, dependiendo de lo que realmente es foo. foo.GetColumnValues<int>(dm.mainColumn)puede ser el camino a seguir.
Major Productions
1
Como dije, me doy cuenta de que hay otras formas de hacerlo (indicador booleano, genéricos, anulación del método). Me preguntaba si era posible como parámetro.
Mark Mayo
@ MarkMayo: No entiendo la pregunta si "sabes que también puedes anular el método, usar genéricos, etc. y sabes que hay diferentes maneras de hacer esto, solo sentiste curiosidad si esto era posible" . ¿Entonces sabes todo esto pero tienes curiosidad si es posible?
Tim Schmelter
@TimSchmelter: en la forma que describo. es decir, pasarlo como el segundo parámetro. Resulta que Reed ha dicho algo de lo que estaba buscando: dónde usas (..., tipo de letra). Eso es lo que estaba buscando.
Mark Mayo
1
Buena pregunta, votada, veo que MS usa Type como parámetro para operadores integrados en VB.NET, por ejemplo, trycast, y a menudo he deseado poder hacerlo yo mismo en C # / VB, de la manera que usted describe.
Chalky

Respuestas:

213

Hay dos enfoques comunes. Primero, puedes pasarSystem.Type

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

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

Esto se llamaría así: int val = (int)GetColumnValue(columnName, typeof(int));

La otra opción sería usar genéricos:

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

Esto tiene la ventaja de evitar el boxeo y proporcionar algún tipo de seguridad, y se llamaría así: int val = GetColumnValue<int>(columnName);

Reed Copsey
fuente
1
También puede hacer un método de extensión, público estático T GetColumnValue <T> (esta cadena columnName) {...} luego puede decir foo.GetColumnValues ​​<string> (dm.mainColumn)
Joshua G
Pero, ¿cómo define un método que tiene varios argumentos y uno de ellos debe ser genérico? Dado que el genérico se define antes de la lista de argumentos del método, ¿cómo sabe cuál debería ser un genérico?
BadmintonCat
55
@BadmintonCat T Foo<T,U>(string arg1, U arg2)o similar
Reed Copsey
Cuando se utiliza el primer enfoque, ¿hay alguna forma de asignar un valor predeterminado para escribir? (por ejemplo, algo así object GetColumnValue(string columnName, Type type = object). Eso no parece funcionar para mí, pero sería útil saberlo.
Dave Cole
22

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

Alternativamente, podría usar un método genérico:

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

y luego puedes usarlo como:

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

Puede pasar un tipo como argumento, pero para hacerlo debe usar typeof:

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

El método debería aceptar un parámetro con tipo Type .


donde el método GetColumns llamará a un método diferente dentro dependiendo del tipo pasado.

Si desea este comportamiento, no debe pasar el tipo como argumento, sino utilizar un parámetro de tipo.

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

O usando genéricos:

foo.GetColumnValues<int>(dm.mainColumn);
foo.GetColumnValues<string>(dm.mainColumn);
Danny Varod
fuente
3
No te vi, pero probablemente fue porque estás mostrando cómo se llamaría y no especificaste la definición de la función
JConstantine
3
Odio cuando la gente necesita comer con cuchara. La respuesta + una lectura realmente breve de MSDN es suficiente. Sospecho que los votantes desalentadores están respondiendo compitiendo por rep, qué mezquino.
Danny Varod
1

Puedes hacer esto, solo envuélvelo typeof()

foo.GetColumnValues(typeof(int))

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

Puede usar un argumento de tipo Type - iow, pass typeof (int). También puede usar genéricos para un enfoque (probablemente más eficiente).

Error interno de servidor 500
fuente
0

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

Y llámalo así:

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