在Linq中安全地解除引用FirstOrDefault调用c#

sam*_*amy 17 c# linq syntax

为了简洁起见,在我的代码中,我希望能够执行以下操作:拥有一个集合,找到匹配lambda表达式的第一个元素; 如果存在,则返回属性或函数的值.如果它不存在,则返回null.

更新的例子w.类

我们有一些东西

class Stuff
{
    public int Id { get; set; }
    public string Value { get; set; }
    public DateTime? ExecutionTime { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的目标是在调用它时很好地返回

var list = new Stuff[] { new Stuff() { Id = 1, Value = "label", ExecutionTime = DateTime.Now } };

// would return the value of ExecutionTime for the element in the list
var ExistingTime = list.FirstOrDefault(s => s.Value.Contains("ab")).ExecutionTime;

// would return null
var NotExistingTime = list.FirstOrDefault(s => s.Value.Contains("zzz")).ExecutionTime; 
Run Code Online (Sandbox Code Playgroud)

是否可以使用一些linq-syntax-fu或者我必须在继续之前明确检查返回值?

原始例子w.字符串

var stuff = {"I", "am", "many", "strings", "obviously"};

// would return "OBVIOUSLY"
var UpperValueOfAString = stuff.FirstOrDefault(s => s.contains("bvi")).ToUpper();

// would return null
var UpperValueOfAStringWannabe = stuff.FirstOrDefault(s => s.contains("unknown token")).ToUpper();
Run Code Online (Sandbox Code Playgroud)

注释:我不应该在我的原始示例中使用字符串,因为它通过将其集中在ToUpper方法和字符串类上来稍微扭曲问题.请考虑更新的示例

Ani*_*Ani 32

为什么不这样做:

stuff.Where(s => s.contains("bvi"))
     .Select(s => s.ToUpper())
     .FirstOrDefault()
Run Code Online (Sandbox Code Playgroud)

如果您有"非默认默认值",则可以执行以下操作:

stuff.Where(s => s.contains("bvi"))
     .Select(s => s.ToUpper())
     .DefaultIfEmpty("Something Else")
     .First()
Run Code Online (Sandbox Code Playgroud)

  • +1仅对使用Linq扩展名的答案. (3认同)
  • @samy不,最后的`FirstOrDefault`将在第一个停止迭代,如果有第一个.上面的linq都没有要求全列表解析工作,它都是延迟的. (2认同)
  • @Samy:不,我刚问过[一个非常相似的问题](http://stackoverflow.com/questions/10110013/order-of-linq-extension-methods-does-not-affect-performance) .请参阅[Eric Lippert的回答](http://stackoverflow.com/a/10110269/284240). (2认同)

yam*_*men 9

我喜欢这个作为扩展方法:

public static U SelectMaybe<T, U>(this T input, Func<T,U> func)
{
    if (input != null) return func(input);
    else return default(U);
}
Run Code Online (Sandbox Code Playgroud)

用法:

var UpperValueOfAString = stuff.FirstOrDefault(s => s.Contains("bvi")).SelectMaybe(x => x.ToUpper());
var UpperValueOfAStringWannabe = stuff.FirstOrDefault(s => s.Contains("unknown token")).SelectMaybe(x => x.ToUpper());
Run Code Online (Sandbox Code Playgroud)

这将链返回默认值(null在这种情况下,但对于该类型是正确的),或调用相关函数并返回该值.