代码之家  ›  专栏  ›  技术社区  ›  dance2die

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

  •  3
  • dance2die  · 技术社区  · 15 年前

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

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

    这里的目标是,我想让这个表达式稍微更通用一点,这样我就可以传递任何可以为空的类型,比如, DateTime?

    这是我刚开始使用的一个非功能代码,但不确定 哪里 指定可以为空的 类型 .

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

    是否可以指定泛型类型 或者我应该创建一个命名函数来这样做?

    3 回复  |  直到 15 年前
        1
  •  3
  •   John K    15 年前

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

        2
  •  1
  •   Reed Copsey    15 年前

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

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

    这两种情况都处理得很好。

        3
  •  1
  •   Lee    15 年前

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

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