隐藏三元运算符的扩展

本文关键字:运算符 扩展 三元 隐藏 | 更新日期: 2023-09-27 17:50:04

假设我有一个三元运算:

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

但是那很难看。是否有一种方法来重新工作,我不需要框和打开返回值?我对扩展/泛型很陌生,所以如果这很简单,请原谅我。

隐藏三元运算符的扩展

你可以这样做:

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

所以首先,你应该接受委托而不是反射。还可以使用第二个泛型参数来处理返回对象的实际类型:

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

不需要扩展方法的备选答案:

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