Вопрос о выводе универсального типа интерфейса C #

#c# #generics #types #inference

#c# #общие сведения #типы #вывод

Вопрос:

Я не уверен, как сформулировать этот вопрос кратко, не приводя просто пример, поэтому здесь:

 public interface IThing<T>
{
    void Do(T obj);
}

public class ThingOne : IThing<int>
{
    public void Do(int obj)
    {
    }
}

public class ThingTwo : IThing<string>
{
    public void Do(string obj)
    {
    }
}

public class ThingFactory
{
    public IThing<T> Create<T>(string param)
    {
        if (param.Equals("one"))
            return (IThing<T>)new ThingOne();

        if (param.Equals("two"))
            return (IThing<T>)new ThingTwo();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var f = new ThingFactory();

        // any way we can get the compiler to infer IThing<int> ?
        var thing = f.Create("one");

    }
}
  

Комментарии:

1. Это не вывод типа — ваш возвращаемый тип не является статическим, т. Е. Заранее неизвестно, будет ли возвращен TypeOne или TypeTwo.

2. Добавляя к ответам, ваш код не должен быть даже компилируемым без этого типа «вывод» из-за Create<T> метода и особенно из-за ваших приведений. new ThingTwo() не может быть приведено к IThing<T> , то же самое верно для ThingOne . Похоже, вам нужен динамически типизированный язык. Или вы допустили (собираетесь допустить) ошибку в своем проекте.

Ответ №1:

Вопрос, похоже, здесь:

 // any way we can get the compiler to infer IThing<int> ?
var thing = f.Create("one");
  

Нет. Вам нужно будет явно указать тип:

 var thing = f.Create<int>("one");
  

Вы не можете вывести тип возвращаемого значения, не имея параметра, используемого специально в методе. Компилятор использует параметры, переданные методу, для вывода типа T , и в данном случае это параметр с одной строкой, без параметров типа T . Таким образом, нет способа вывести это для вас.

Ответ №2:

Нет, вы не можете этого сделать, потому что результат вашего Create фабричного метода будет оцениваться во время выполнения на основе значения параметра. Универсальные интерфейсы предназначены для обеспечения безопасности во время компиляции, и в вашем случае у вас не может быть такой безопасности, потому что значение параметра будет известно только во время выполнения.