21

Вопрос по c#, generics, syntax – Есть ли в C # «анонимный» общий тег, например «?» в Java?

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

Foo<?> x;

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

Какой тип шаблона окончательно решен?

от Orion Adrian
6 ответов
5

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

1

Нет

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

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

11

Хотя по общему признанию, это не чистый подход, использование

Foo<object> x также может подойти.

@Dani,List<object>.Add включает любые типы структур вNullable<>s, таким образом, комментарий Марка остается в силе.

от 

-1: используяobject ограничить универсальный тип всеми типами, которые имеют общий суперклассobject.

от 

Я признаю, что вы правы.

от 

Работает со всем: примитивами, объектами классов, структурами, перечислениями ...List<object> list = new List<object>(); list.Add(1); list.Add(new DateTime()); list.Add(new MyStruct()); list.Add(MyEnum.Enum1);

от 

Не могли бы вы тогда, пожалуйста, отменить мой ответ?

от 
3

Не совсем верно

что в 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.
28

Краткий ответ: нет. В 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); 
    }
}

Это на самом деле не отвечает на вопрос. Ответ "нет". Трюк, показанный выше, демонстрирует обходной путь для преобразования захвата Java в C #, который работает с преобразованием вызова метода, но не будет полезным при преобразовании присваивания или в приведенном выражении.

от 

Хорошо-хорошо. Я добавил де 'нет' в начале. :) И, ребята, вы знаете, вы можете редактировать мой ответ, верно?

от 

И это даже помечено как принятый ответ.

от 

На самом деле, этот ответ - самый длинный способ сказать «нет». Я когда-либо видел :)

от 

C # -подобный вывод работает также в Java 6. Все еще используется & lt;? & Gt; в Java тогда?

от 
15

AFAIK вы не можете сделать это в C #. То

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

class Foo
{
}

class Foo<T> : Foo
{
}

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

Foo t = new Foo<int>();

Похожие вопросы