Можно ли использовать вывод типа для первого параметра и указать другой тип - PullRequest
2 голосов
/ 17 сентября 2011

Это простой надуманный пример, но, надеюсь, проиллюстрирует мой запрос.

public class Test
{
    public string Name = "test";
}


public static class Ext 
{
     public static Test ConvertToTest<T1>(this T1 source) 
     {
         return new Test();
     }

     public static T2 Convert<T1,T2>(this T1 source) where T2 : new()
     {
         return new T2();
     }
}

Для ConvertToTest нужен только один тип, поэтому следующая компиляция

    Ext.ConvertToTest<string>("hello");
    "hello".ConvertToTest();

В последнем используется тип-Интерфейс и это означает, что он также работает с анонимными классами, например

    var anon = (new { Name = "test" }) ;
    anon.ConvertToTest();

Однако это жестко закодировано, чтобы всегда использовать класс Test, тогда как я хочу иметь возможность указать тип, как во втором методе

Я могу написать

   Ext.Convert<string, Test>("hello");

, и это компилируется, потому что я знаю оба типа во время компиляции, но я не могу использовать его с анонимными классами, и я не могу найти способ использования типа-inference плюс дополнительный тип

Было бы неплохо, если бы я мог сделать что-то вроде

    anon.Convert<,Test>()  ;

, и компилятор знал бы, что использовать логический вывод для первого типа (который не указан)и использовать тест в качестве второго типа.

Есть ли способ обойти эту проблему?

Ответы [ 2 ]

4 голосов
/ 17 сентября 2011

Вы не можете делать то, что просите, с помощью одного метода, но если вы умны и хотите определить пару разных классов, вы сможете сделать синтаксис таким, как этот:

var test = Ext.Convert("hello").To<Test>();

Просто сделайте Convert основанным на одном универсальном типе, и пусть он вернет универсальный тип, основанный на этом:

public Converter<T> Convert<T>(T source)
{
    return new Converter<T>(source);
}

Затем добавьте метод к возвращаемому типу, который служит базовымОбертка для вашего оригинального метода:

public class Converter<T>
{
    T _source;
    internal Converter(T source)
    {
        _source = source;
    }
    public T2 To<T2>()
    {
        return Ext.Convert<T, T2>(_source);
    }
}
0 голосов
/ 17 сентября 2011

Есть способ сделать то, что вы хотите. Вы используете шаблон шаблона - это немного клудж, но он позволяет вывести оба типа. Его также можно использовать для вывода анонимных типов.

Вот оно:

public static T2 Convert<T1,T2>(this T1 source, Func<T2> template)
    where T2 : new()
{
    return new T2();
}

Вы можете назвать это так:

var anon = (new { Name = "test" }) ;
anon.Convert(() => new Test());

Что не слишком далеко от вашего псевдокода.

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