【问题标题】:Extension to Hide Ternary Operator隐藏三元运算符的扩展
【发布时间】:2014-03-13 20:39:23
【问题描述】:

假设我有一个三元运算:

db.Scanners.FirstOrDefault(s => s.ScannerID==24) != null 
       ? db.Scanners.FirstOrDefault(s => s.ScannerID==24).FriendlyName 
       : "N/A";

我想写一个 LINQ 扩展来隐藏操作。我最好的尝试是:

public static object PropertyOrNull<T>(this T source, string property)
{
    if (source == null || source.GetType().GetProperty(property) == null)
         return null;

    return source.GetType().GetProperty(property).GetValue(source, null);
}  

我现在可以通过以下方式拨打电话:

(string)db.Scanners.FirstOrDefault(s => s.ScannerID == 24)
           .PropertyOrNull("FriendlyName");

但这很丑。有没有办法在我不必装箱和拆箱返回值的情况下重新工作?我对扩展/泛型很陌生,如果这很简单,请原谅我。

【问题讨论】:

  • 这不是 LINQ 扩展。这只是一个扩展。 LINQ 只是 System.Linq 命名空间中的扩展方法的集合。您不是在那里添加一个,而是在其他地方添加自己的扩展。

标签: c# generics reflection extension-methods


【解决方案1】:

你可以这样做:

public static TProperty TryGetValue<T, TProperty>(
    this T source,
    Func<T, TProperty> getter,
    TProperty defaultValue = default(TProperty))
{
    if (source == null)
         return defaultValue;

    return getter(source);
}

像这样使用它:

db.Scanners.FirstOrDefault(s => s.ScannerID == 24)
           .TryGetValue(s => s.FriendlyName, "N/A");

这种方法比使用反射要快得多,也更安全,因为在编译时会检测到无效的属性名称。它也是强类型的,这意味着您不需要转换结果。

另一种不需要新扩展方法的方法是在调用FirstOrDefault之前投影序列:

db.Scanners.Select(s => s.FriendlyName)
           .FirstOrDefault() ?? "N/A";

【讨论】:

  • 太棒了。特别是使用可选的 defaultValue。非常感谢你
【解决方案2】:

因此,首先,您应该简单地接受委托,而不是反射。您还可以使用第二个通用参数来处理返回对象的 实际 类型:

public static TResult Use<T, TResult>(this T obj, Func<T, TResult> selector)
    where TResult : class
    where T : class
{
    if (obj == null)
        return null;
    return selector(obj);
}

然后你可以这样称呼它:

var str = something.Use(s => s.ToString());

【讨论】:

    【解决方案3】:

    不需要扩展方法的替代答案:

    var friendlyName = db.Scanners.Where(s => s.ScannerID == 24)
                         .Select(s => s.FriendlyName).FirstOrDefault() ?? "N/A";
    

    【讨论】:

    • 这只是一个选项,如果你有一个 IEnumerable 开始。如果所讨论的项目不是序列的一部分,那么这不是那么可行。
    • 这很公平。我认为 OP 专门试图避免双重 FirstOrDefault 反模式,但你是对的,这是我的一个假设。
    猜你喜欢
    • 1970-01-01
    • 2021-12-05
    • 2014-10-10
    • 2017-09-20
    • 1970-01-01
    • 2016-10-24
    • 2021-12-08
    • 2020-10-21
    • 2012-09-07
    相关资源
    最近更新 更多