Есть ли в C # «анонимный» универсальный тег, например «?» в Java? - PullRequest
22 голосов
/ 22 сентября 2008

В Java можно объявить переменную, параметризованную «неизвестным» универсальным типом, который выглядит следующим образом:

Foo<?> x;

Есть ли эквивалентная конструкция для этого знака вопроса в C #?

Ответы [ 6 ]

28 голосов
/ 22 сентября 2008

Короткий ответ - нет. В C # нет эквивалентной функции.

Обходной путь от C # с точки зрения разработчика Java от Dare Obasanjo:

В некоторых случаях может потребоваться создать метод, который может работать со структурами данных, содержащими любой тип, в отличие от тех, которые содержат определенный тип (например, метод для печати всех объектов в структуре данных), но при этом использовать преимущества преимущества строгой типизации в дженериках. Механизм для указания этого в C # осуществляется с помощью функции, называемой выводом универсального типа, в то время как в Java это делается с использованием подстановочных типов. В следующих примерах кода показано, как оба подхода приводят к одному и тому же результату.

C # код

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

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); 
    }
}
15 голосов
/ 22 сентября 2008

AFAIK вы не можете сделать это в C #. То, что делает BCL и существует множество примеров, - это создать класс, который не является универсальным, а затем создать универсальный класс, который наследует базовое поведение от предыдущего. Смотрите пример ниже.

class Foo
{
}

class Foo<T> : Foo
{
}

Вы можете написать что-то вроде этого:

Foo t = new Foo<int>();
12 голосов
/ 06 июля 2012

Хотя это не совсем чистый подход, использование Foo<object> x также может подойти.

5 голосов
/ 22 сентября 2008

В C # нет эквивалентного синтаксиса.

3 голосов
/ 22 сентября 2008

Это не совсем верно, что в C # нет эквивалента. Не существует статического эквивалента, который вы можете использовать как тип или вызывать методы, достаточно верно. Для этого используйте ответ Хорхе .

С другой стороны, иногда вам нужна эквивалентная идея для отражения, и там есть эквивалент. Если у вас есть:

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

вы можете получить Type, который представляет IFoo<int>, используя typeof(IFoo<int>). Менее известным и частичным ответом на ваш вопрос является то, что вы также можете получить Type, который представляет IFoo<T>, используя typeof(IFoo<>).

Это полезно, когда вы хотите использовать IFoo<T> для некоторых T через отражение и не будете знать T до времени выполнения.

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.
1 голос
/ 22 сентября 2008

Нет, в C # на самом деле нет той же концепции. Вам нужно будет обратиться к базовому классу Foo (возможно, не универсальному Foo) или сделать метод, с которым вы работаете, самим generic (чтобы вы могли ссылаться на Foo и позволить вызывающей стороне вашего метода определить, какой T есть).

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...