如何将泛型类型参数传递给 lambda 表达式?

发布于 2024-08-08 13:57:49 字数 767 浏览 0 评论 0原文

我有一个 lambda 表达式,它接受 int? (可空整数)、
如果值存在或DBNull.Value<,则返回值/code>否则。

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

这里的目标是,我想让该表达式稍微更通用一些,以便我可以传递任何可空类型,例如 DateTime?

所以这是我开始的非功能代码,但不确定在哪里指定 nullable 的类型

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

是否可以指定泛型类型或者我应该创建一个命名函数来执行此操作?

I have a lambda expression which accepts, a int? (nullable integer),
which returns value if value exists or DBNull.Value otherwise.

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?

So here is a non-functional code I was starting off with, but not sure where to specify nullable's type.

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

罪歌 2024-08-15 13:57:49

由于问题的目的是使用 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 的数据类型属于结构本身,而不是 Nullable 类型包装器。显然,当调用者使用 lambda 参数并且 lambda 参数显示结构体值或 null 时,调用者使用的 Nullable 值已被解析或“解包”;此时(或者据我所知)看不到 Nullable 包装器。可以通过在 lambda 中的 v 处放置调试断点并检查其值来证明此行为。
这种行为的好处是 lambda 对于 Nullable 和非 Nullable 类型同样有效——它不受限制。

Since the purpose of the question is to use a lambda expression, here is a solution. 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. 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; the Nullable wrapper is nowhere to be seen at this point (or as far as I can find). This behaviour can be proved by putting a debug breakpoint in the lambda at v and inspecting its value.
The good side effect of this behaviour is the lambda works equally well for both Nullable and non-Nullable types -- it's not restricted.

暗喜 2024-08-15 13:57:49

您可以在 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

它正确处理了这两种情况。

Instead of using generics, you can just make an extension method on Object to do the conversion.

Here's a sample program. The ToDbObject extension does the conversion:

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.

哑剧 2024-08-15 13:57:49

我认为您可以通过创建一个委托工厂方法来做到这一点,您可以在其中指定泛型类型参数:

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

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));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文