【问题标题】:Is the c# coalescence the same as an if statement when setting to null?设置为null时,c#合并是否与if语句相同?
【发布时间】:2020-04-15 19:41:21
【问题描述】:

这两个语句是一样的吗?

if (dep.BirthDate.HasValue) {
  myObj.GetType().GetProperty("birthdate").SetValue(myObj, (DateTime)dep.BirthDate, null);
}


myObj.GetType().GetProperty("birthdate").SetValue(myObj, dep.BirthDate ?? null, null);

我只想设置有值的生日,但我想在 1 行中完成。

【问题讨论】:

  • 不,不一样 - 在第一种情况下,您仅在指定出生日期时设置属性值(否则它将具有原始值),在第二种情况下,您始终为属性分配值(或者出生日期或为空)。结果可能非常不同,例如如果属性设置器抛出ArgumentNullException
  • 好的,有没有办法在没有 if 的情况下获得 1 行中的第一个条件?
  • 将其封装在执行 if-check 的方法中是唯一的方法,AFAIK。
  • 同意@IanKemp - 你可以写PropertyInfo扩展
  • 如果birthdateDateTime 的类型,那么dep.BirthDate ?? default(DateTime) 应该这样做...根据您之前的问题,您似乎正在重新发明AutoMapper

标签: c# null nullable gettype null-coalescing


【解决方案1】:

正如@IanKemp 所建议的,当您想跳过属性分配时,您无法避免 if-check。不要与分配默认值混淆。

最简单的解决方案是将可空值检查和属性赋值封装到单个操作中。为了避免传递PropertyInfo,可以使用扩展方法:

public static class ReflectionExtensions
{
    public static void SetValueIfNotNull<T>(this PropertyInfo prop, object obj, T? maybe)
        where T : struct
    {
        if (maybe.HasValue)
            prop.SetValue(obj, maybe.Value);
    }
}

用法:

myObj.GetType().GetProperty("birthdate").SetValueIfNotNull(myObj, dep.BirthDate);

或者,如果您经常使用可空值并且属性设置不是您唯一要做的事情,那么您可以编写一个可空扩展,它将您的代码带回不可空路径:

public static class NullableExtensions
{
    // Note that action has non-nullable argument
    public static void Invoke<T>(this Nullable<T> nullable, Action<T> action)
        where T: struct
    {
        if (nullable.HasValue)
            action(nullable.Value);
    }
}

这种方法交换了一些东西 - 现在您可以在 nullable 具有值的情况下对可空变量的值调用操作:

dep.BirthDate.Invoke(date => myObj.GetType().GetProperty("birthday").SetValue(myObj, date));

如果您要调用单参数函数,甚至可以采用这种方式

dep.BirthDate.Invoke(myObj.SetProperty<DateTime>("birthday"));

【讨论】:

    【解决方案2】:

    首先,这听起来像是一个速度问题。所以,速度咆哮:https://ericlippert.com/2012/12/17/performance-rant/

    其次,将很多东西放在一行中的唯一代价是:

    • 花时间阅读它
    • 要花时间理解它
    • 不知何故更糟尝试调试它的时间

    第一个有 6(六)个地方,其中一个是 null 引用异常可能会命中。也是演员和反思。这是一个异常的滋生地。从现在起 6 个月后必须调试该线路的任何人都会从中得到噩梦。那可能就是你。

    代码的可读性和可调试性应该是第一位的。尝试将其限制为 1 个操作/代码行,将其结果分配给临时变量,以获得有用的异常。 永远不要担心临时变量对性能的影响。在编译器、JiT 编译器和死代码检测之间,无论如何都会在发布版本中删除。

    【讨论】:

    • 我没有看到任何迹象表明这个问题与性能有关。对我来说,看起来他只是想要更简洁的代码
    • 你只是更干净,但不会那么挑剔。非常感谢您提供的信息。
    猜你喜欢
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-27
    • 2019-11-14
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多