【问题标题】:Is it possible to using Type Inference for the first parameter and specify another type是否可以对第一个参数使用类型推断并指定另一种类型
【发布时间】:2011-09-16 22:06:44
【问题描述】:

这是一个简单的人为示例,但希望能说明我的查询。

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 只需要一个Type,所以下面编译

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

最后一个使用类型干扰,这意味着它也适用于匿名类,例如

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

然而,这被硬编码为始终使用类 Test,而我希望能够像在第二种方法中那样指定类型

我会写

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

这会编译,因为我在编译时知道这两种类型,但我不能将它与匿名类一起使用,而且我找不到使用类型推断和额外类型的方法

如果我能做类似的事情就好了

    anon.Convert<,Test>()  ;

并且编译器会知道将推理用于第一种类型(未指定)并将 Test 用作第二种类型。

有没有办法解决这个问题?

【问题讨论】:

    标签: c# c#-3.0 extension-methods type-inference


    【解决方案1】:

    你不能在一个方法上做你要求的事情,但是如果你很聪明并且愿意定义几个不同的类,你应该能够使这样的语法成为可能:

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

    【讨论】:

    • 谢谢。不知道是否聪明,但我想我足够聪明,可以在完成这项工作时进行剪切和粘贴。我认为有一些语法错误,例如 Converter 类不应该从自身继承,最后一行应该使用 _source 而不是 source。并且我把Convert的定义改成了public static Converter Convert(this T source),这样就可以作为扩展方法使用了。
    • @sgmoore:呵呵,有时需要一个聪明的人才能涉足我匆忙拼凑的代码。顺便说一句,扩展方法是个好主意。
    【解决方案2】:

    有一种方法可以做你想做的事。您使用模板模式 - 它有点杂乱,但它允许您推断两种类型。它也可以用来推断匿名类型。

    这里是:

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

    这与您的伪代码相距不远。

    【讨论】:

      猜你喜欢
      • 2021-10-16
      • 1970-01-01
      • 2022-10-24
      • 2014-06-21
      • 1970-01-01
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      • 2023-03-30
      相关资源
      最近更新 更多