Pergunta

Em Java, pode-se declarar uma variável parametrizada por um tipo genérico "desconhecido", que tem esta aparência:

Foo<?> x;

Existe uma construção equivalente a este ponto de interrogação, em C #?

Foi útil?

Solução

A resposta curta não é. Não é uma característica equivalente em C #.

A solução, de C # a partir perspectiva de um desenvolvedor Java por Atreva Obasanjo:

Em certos casos, pode-se necessário criar um método que pode operar em estruturas de dados que contenham qualquer tipo, em oposição aos que contêm um tipo específico (por exemplo, um método para imprimir todos os objectos de uma estrutura de dados) enquanto ainda aproveitando os benefícios de tipagem forte em genéricos. O mecanismo para especificar isso em C # é através de um recurso chamado de tipo genérico inferência enquanto em Java isso é feito usando tipos curinga. Os exemplos de código a seguir mostram como as duas abordagens levam ao mesmo resultado.

C # Code

using System;
using System.Collections;
using System.Collections.Generic; 

class Test{

    //Prints the contents of any generic Stack by 
    //using generic type inference 
    public static void PrintStackContents<T>(Stack<T> s){
        while(s.Count != 0){
            Console.WriteLine(s.Pop()); 
        } 
    }

    public static void Main(String[] args){

    Stack<int> s2 = new Stack<int>(); 
    s2.Push(4); 
    s2.Push(5); 
    s2.Push(6); 

    PrintStackContents(s2);     

    Stack<string> s1 = new Stack<string>(); 
    s1.Push("One"); 
    s1.Push("Two"); 
    s1.Push("Three"); 

    PrintStackContents(s1); 
    }
}

código Java

import java.util.*; 

class Test{

    //Prints the contents of any generic Stack by 
    //specifying wildcard type 
    public static void PrintStackContents(Stack<?> s){
        while(!s.empty()){
            System.out.println(s.pop()); 
        }
    }

    public static void main(String[] args){

    Stack <Integer> s2 = new Stack <Integer>(); 
    s2.push(4); 
    s2.push(5); 
    s2.push(6); 

    PrintStackContents(s2);     

    Stack<String> s1 = new Stack<String>(); 
    s1.push("One"); 
    s1.push("Two"); 
    s1.push("Three");   

    PrintStackContents(s1); 
    }
}

Outras dicas

AFAIK você não pode fazer isso em C #. O que a BCL faz e existem plenties de exemplos não é criar uma classe que não é genérica e, em seguida, criar uma classe genérica que herda o comportamento de base da anterior. Veja o exemplo abaixo.

class Foo
{
}

class Foo<T> : Foo
{
}

O que você pode escrever algo como isto:

Foo t = new Foo<int>();

Embora não reconhecidamente estar a abordagem limpa, usando Foo<object> x também podem ser adequados.

Não há uma sintaxe equivalente em C #.

Não é (muito) verdade que não há equivalente em C #. Não há equivalente estática que você pode usar como um tipo, ou chamar métodos, é verdade. Para isso, use resposta de Jorge .

Por outro lado, às vezes você precisa a idéia equivalente para reflexão, e não há um equivalente lá. Se você tem:

interface IFoo<T>
{
  T Bar(T t, int n);
}

você pode obter um Type que representa IFoo<int> usando typeof(IFoo<int>). Menos conhecido, e uma resposta parcial à sua pergunta, é que você também pode obter um Type que representa IFoo<T> usando typeof(IFoo<>).

Isto é útil quando você quiser usar IFoo<T> por algum T através da reflexão e não saberá T até a execução.

Type theInterface = typeof(IFoo<>);
Type theSpecificInterface = theInterface.MakeGenericType(typeof(string));

// theSpecificInterface now holds IFoo<string> even though we may not have known we wanted to use string until runtime

// proceed with reflection as normal, make late bound calls / constructions, emit DynamicMethod code, etc.

Não, não é realmente o mesmo conceito em C #. Você precisaria para se referir a uma classe base de Foo (talvez um Foo não-genérico), ou fazer o método que você está trabalhando em si genérica (de modo que você pode se referir a Foo, e deixar o chamador do seu método de determinar o que T é).

Espero que ajude.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top