简体   繁体   English

如何将Generic Type参数传递给lambda表达式?

[英]How to pass Generic Type parameter to lambda expression?

I have a lambda expression which accepts, a int? 我有一个lambda表达式,接受一个int? (nullable integer), (可以为空的整数),
which returns value if value exists or DBNull.Value otherwise. 如果值存在则返回值,否则返回DBNull.Value

Func<int?, object> getId = id => id.HasValue ? id.Value : (object)DBNull.Value;

The goal here is that, I want to make that expression slightly a bit more generic so that I can pass any nullable types like, DateTime? 这里的目标是,我想使该表达式略微更通用,以便我可以传递任何可以为null的类型,如DateTime?

So here is a non-functional code I was starting off with, but not sure where to specify nullable's type . 所以这是一个我开始使用的非功能性代码,但不知道在哪里指定nullable的类型

int? imageId;
DateTime? actionDate;
Func<Nullable<T>, object> getValue = 
    id => id.HasValue ? id.Value : (object) DBNull.Value;
SaveImage(getValue(imageId), getValue(actionDate));

Is it possible to specify generic type or should I create a named function to do so? 是否可以指定泛型类型或者我应该创建一个命名函数来执行此操作?

Since the purpose of the question is to use a lambda expression, here is a solution. 由于问题的目的是使用lambda表达式,因此这是一个解决方案。 It takes a different route by using weak typing instead of the proposed strong typing, but accomplishes the same thing nonetheless. 通过使用弱类型而不是建议的强类型,它采用不同的路线,但仍然完成相同的事情。

        // A lambda solution
        Func<object, object> fnGetValue =
            v =>
                ReferenceEquals(v, null)
                ? DBNull.Value
                : v;


        // Sample usage
        int? one = 1;
        int? two = null;
        object o1 = fnGetValue(one); // gets 1
        object o2 = fnGetValue(two); // gets DBNull

Edit : This loose typing works because the data type of the lambda argument v is of the struct itself and is not the Nullable type wrapper. 编辑 :这种松散的输入有效,因为lambda参数v的数据类型是struct本身,而不是Nullable类型的包装器。 Apparently the Nullable value that the caller uses has been resolved or 'unwrapped' by the time it hits the lambda argument and the lambda argument reveals a struct value or null; 显然,调用者使用的Nullable值在到达lambda参数时已被解析或“解包”,并且lambda参数显示结构值或null; the Nullable wrapper is nowhere to be seen at this point (or as far as I can find). Nullable包装器在这一点上无处可见(或者据我所知)。 This behaviour can be proved by putting a debug breakpoint in the lambda at v and inspecting its value. 可以通过在lambda中将调试断点放在v并检查其值来证明此行为。 The good side effect of this behaviour is the lambda works equally well for both Nullable and non-Nullable types -- it's not restricted. 这种行为的良好副作用是lambda同样适用于Nullable和非Nullable类型 - 它不受限制。

Instead of using generics, you can just make an extension method on Object to do the conversion. 您可以在Object上创建一个扩展方法来进行转换,而不是使用泛型。

Here's a sample program. 这是一个示例程序。 The ToDbObject extension does the conversion: ToDbObject扩展进行转换:

using System;

static class Program
{
    static object ToDbObject(this object value)
    {
        return value ?? DBNull.Value;
    }
    static void Main(string[] args)
    {
        int? imageId = 3; 
        DateTime? actionDate = null;

        Console.WriteLine("ImageId {0}: [{1}] - {2}", imageId, imageId.ToDbObject(), imageId.ToDbObject().GetType());
        Console.WriteLine("actionDate {0}: [{1}] - {2}", actionDate, actionDate.ToDbObject(), actionDate.ToDbObject().GetType());
        Console.ReadKey();
    } 
}

The above prints: 以上打印:

ImageId 3: [3] - System.Int32
actionDate : [] - System.DBNull

It's correctly handling both cases. 它正确处理这两种情况。

I think you can do it by creating a delegate factory method where you can specify the generic type parameter: 我认为您可以通过创建委托工厂方法来执行此操作,您可以在其中指定泛型类型参数:

public static Func<Nullable<T>, object> CreateGetValueFunc<T>() where T : struct
{
    return id => id.HasValue ? id.Value : (object)DBNull.Value;
}

And you can use it in your example like this: 你可以在你的例子中使用它,如下所示:

SaveImage(
    CreateGetValueFunc<int>()(imageId),
    CreateGetValueFunc<DateTime>()(actionDate));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM