Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C泛型方法,可以从表达式参数推断其类型参数_C#_Generics_Types_Interface_Type Inference - Fatal编程技术网

C# C泛型方法,可以从表达式参数推断其类型参数

C# C泛型方法,可以从表达式参数推断其类型参数,c#,generics,types,interface,type-inference,C#,Generics,Types,Interface,Type Inference,我正在尝试创建一个方法,该方法可以接受对象的类型作为类型参数,以及对对象的属性之一及其类型的引用。大概是这样的: service.DoWorkdt=>dt.Ticks 我研究了其他图书馆是如何做这些事情的,并得出以下定义: interface IService { void DoWork<TObject, TProperty>(Expression<Func<TObject, TProperty>> propertySelector); } 理想情况

我正在尝试创建一个方法,该方法可以接受对象的类型作为类型参数,以及对对象的属性之一及其类型的引用。大概是这样的:

service.DoWorkdt=>dt.Ticks

我研究了其他图书馆是如何做这些事情的,并得出以下定义:

interface IService
{
    void DoWork<TObject, TProperty>(Expression<Func<TObject, TProperty>> propertySelector);
}
理想情况下,用户可以传入对象的类型,然后使用表达式选择其每个属性。然后,我的方法可以知道所选的表达式及其类型和对象的类型

但是,以这种方式调用该方法会导致以下错误:

Using the generic method 'IService.DoWork<TObject, TProperty>(Expression<Func<TObject, TProperty>>)' requires 2 type arguments
如果我指定了物业的类型,那么一切正常:

  service.DoWork<DateTime, long>(dt => dt.Ticks);
  service.DoWork<DateTime, TimeSpan>(dt => dt.TimeOfDay);
  service.DoWork<DateTime, int>(dt => dt.Second);
但是,这似乎是多余的。编译器可以从我提供的表达式参数中提取类型,据我所知,许多其他库使用这种类型推断来提供干净的接口Linq、MOQ、FluentAssertion等等

我想我需要以某种方式改变我的方法定义,但我似乎找不到一个正确的方法

PS:这是完整的代码片段

using System;
using System.Linq.Expressions;

namespace GenericTypeInterface
{
    class Program
    {
        static void Main(string[] args)
        {
            IService service = null;

            service.DoWork<DateTime>(dt => dt.Ticks);
            service.DoWork<DateTime>(dt => dt.TimeOfDay);
            service.DoWork<DateTime>(dt => dt.Second);
        }
    }

    interface IService
    {
        void DoWork<TObject, TProperty>(Expression<Func<TObject, TProperty>> propertySelector);
    }
}

通过显式写入lambda参数的类型,可以让它推断两个泛型参数:

service.DoWork((DateTime dt) => dt.Ticks);

很好,这会有用的。然而,我真的希望找到一种不需要强制转换输入参数的方法。我真的想保留service.DoWorkdt=>dt.tick没有其他方法,您在这里定义了一个新变量,除了您之外,没有人知道它应该是日期时间。也许你会更清楚,如果你用x代替dt。@Kobek根本不涉及铸造。这只是指定lambda表达式的参数类型,这是lambda表达式语法的一部分-为lambda表达式的参数指定类型是可选的。不可能按您想要的方式执行,因为DoWork有两个通用参数,您必须同时指定或不指定它们。不能让编译器推断某些泛型参数。也许这将是一个功能在未来,但不是现在。好的,谢谢。我将看看我是否可以重写接口,以便有一种方法可以省略两个paramsType推断,要么完全有效,要么完全无效。您不能指定一个参数,而让编译器猜测所有其他参数。如果DoWork有两个参数,则可以同时指定或不指定。
service.DoWork((DateTime dt) => dt.Ticks);