Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.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# 获得;“对象”;Func的返回类型<;MyClass,对象>;_C#_Reflection_Lambda_Expression - Fatal编程技术网

C# 获得;“对象”;Func的返回类型<;MyClass,对象>;

C# 获得;“对象”;Func的返回类型<;MyClass,对象>;,c#,reflection,lambda,expression,C#,Reflection,Lambda,Expression,假设我对Func的定义如下: Func<MyClass, object> f = o => o.StringProperty; Func f=o=>o.StringProperty; 或 Func f=o=>o.Property.SomeMethod(); 有没有办法在不特别调用返回类型的情况下获取实际的返回类型?您可以通过使用泛型方法使编译器推断类型参数来实现这一点: static Func<T1, R> Infer<T1, R>(Func<

假设我对Func的定义如下:

Func<MyClass, object> f = o => o.StringProperty;
Func f=o=>o.StringProperty;

Func f=o=>o.Property.SomeMethod();

有没有办法在不特别调用返回类型的情况下获取实际的返回类型?

您可以通过使用泛型方法使编译器推断类型参数来实现这一点:

static Func<T1, R> Infer<T1, R>(Func<T1, R> f) { return f; }
这将在编译时将返回类型编码为
func
类型

当然,对于更普遍适用的解决方案,您需要一组
expert
重载来覆盖
Action
Func
,并使用一个、两个、三个等参数


如果您希望在运行时获取返回类型,对于任何类型的
Func
,都可以像ppetrov已经指出的
Func.Method.ReturnType
一样简单。

您可以获得如下返回类型:

f.Method.ReturnType
但这将返回类型
对象
。如果要获取
方法
字符串
或从
对象
派生的内容,除非调用该方法,否则将无法获取信息

实际上可以,但这意味着您必须分解方法核心,然后对其进行分析,以查看方法可以返回什么。但即便如此,也可能有许多不同的回报类型


所以答案是:如果您想知道它返回一个对象,那么可以,否则就不值得麻烦了,最好找到另一种方法来完成您需要的操作。

因为您在运行时从其他源检索这些
Func
委托,类型信息基本上丢失了

相反,在定义这些函数的地方,您可以让调用者利用API在包装委托中对该类型信息进行编码(EDIT:Silly me,此时要简单得多;我们已经有了通用编译时信息):

您的API需要一个
MyClassDelegate
,您可以使用它轻松访问它们的类型:

Console.WriteLine(f1.ReturnType.FullName); //string
Console.WriteLine(f2.ReturnType.FullName); //whatever `SomeMethod()` is declared to return
最后,您还可以调用委托,甚至创建
Func
委托:

f1.Invoke(myClassInstance);
Func<MyClass, object> f3 = f1.Invoke;
f1.Invoke(myClassInstance);
Func f3=f1.Invoke;

“获取”返回类型的准确程度如何?一个假设的例子?@Jon我认为根据编译器知道的事实推断返回类型(在第一个例子中是
string
,在第二个例子中是
SomeMethod
的返回),但是这个例子会在运行时崩溃,因为变量
f
可能被重新分配。假设,如果不能重新分配
f
,您可以通过解析
Func
定义静态确定返回类型。听起来像是Roslyn的候选人;-)根据您的使用情况,也许您可以利用
表达式
API来检查返回类型:(这不是您试图执行的操作的精确实现,只是一个相关的示例)如果您有
Func f1=o=>o.StringProperty;Func f2=o=>f1(o)?甚至
Func f=o=>{throw new NotImplementedException();}?:)@这是一个关于投掷的好问题exception@EugeneD.Gubenkov:当然,如果您已经有了
Func f=s=>s.Length
,并且您确实有
expert(f)
,您将得到一个
Func
——无法恢复已“丢失”的类型信息@EugeneD.Gubenkov:如果你想做得更多,那么你必须使用
表达式和反射;此时不需要LINQ表达式API。关键是在创建委托时让调用方对这些信息进行编码,并利用包装好的委托在整个API中传递信息。谢谢您的详细回答。当我们想要正确地做这些事情时,我们无论如何都应该使用表达式,我明白了。
Expression
用法只有在你想要避免泛型推理的情况下才有帮助。也就是说,您可以使用
Create(Expression function)
并仍然确定使用的类型。但您也可以利用我在更新中使用的泛型类型推断。是的,我只是想找到没有泛型类型的非编译时解决方案。
public class MyClassDelegate
{
    private readonly Func<MyClass, object> Function;

    public Type ReturnType { get; private set; }

    private MyClassDelegate(Func<MyClass, object> function, Type returnType)
    {
        this.Function = function;
        this.ReturnType = returnType;
    }

    public object Invoke(MyClass context)
    {
        return Function(context);
    }

    public static MyClassDelegate Create<TReturnType>(Func<MyClass, TReturnType> function)
    {
        Func<MyClass, object> nonTypedFunction = o => function(o);
        return new MyClassDelegate(nonTypedFunction, typeof(TReturnType));
    }
}
MyClassDelegate f1 = MyClassDelegate.Create(o => o.StringProperty);
MyClassDelegate f2 = MyClassDelegate.Create(o => o.Property.SomeMethod());
Console.WriteLine(f1.ReturnType.FullName); //string
Console.WriteLine(f2.ReturnType.FullName); //whatever `SomeMethod()` is declared to return
f1.Invoke(myClassInstance);
Func<MyClass, object> f3 = f1.Invoke;