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

时间:2009-10-23 21:37:07

标签: c# .net generics lambda

我有一个lambda表达式接受int?(可以为空的整数),
如果值存在则返回值,否则返回DBNull.Value

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

这里的目标是,我想使该表达式略微更通用,以便我可以传递任何可以为空的类型,如DateTime?

所以这是我开始使用的非功能性代码,但不确定 where 指定nullable的类型

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

可以指定泛型类型,还是应该创建一个命名函数呢?

3 个答案:

答案 0 :(得分:3)

由于问题的目的是使用lambda表达式,因此这是一个解决方案。通过使用弱类型而不是建议的强类型,它需要一条不同的路线,但仍然可以完成同样的事情。

        // 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

编辑:这种松散的输入有效,因为lambda参数v的数据类型是struct本身,而不是Nullable类型的包装器。显然,调用者使用的Nullable值在到达lambda参数时已被解析或“解包”,并且lambda参数显示结构值或null; Nullable包装器在这一点上无处可见(或者据我所知)。可以通过在lambda中将调试断点放在v并检查其值来证明此行为。 这种行为的良好副作用是lambda同样适用于Nullable和非Nullable类型 - 它不受限制。

答案 1 :(得分:1)

您可以在Object上创建一个扩展方法来进行转换,而不是使用泛型。

这是一个示例程序。 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();
    } 
}

以上版画:

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

正确处理这两种情况。

答案 2 :(得分:1)

我认为您可以通过创建委托工厂方法来执行此操作,您可以在其中指定泛型类型参数:

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

你可以在你的例子中使用它:

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