Linq SingleOrDefault:如何更改默认值?

Linq SingleOrDefault:如何更改默认值?,linq,Linq,SingleOrDefault返回null,但是如果我想赋值来表示找不到的对象,该怎么办 你可以自己滚 public static T SingleOrDefault<T>(this IEnumerable<T> enumerable, T defaultValue) { if ( 1 != enumerable.Count() ) { return defaultValue; } return enumerable.Single(); } publ

SingleOrDefault返回null,但是如果我想赋值来表示找不到的对象,该怎么办

你可以自己滚

public static T SingleOrDefault<T>(this IEnumerable<T> enumerable, T defaultValue) {
  if ( 1 != enumerable.Count() ) {
    return defaultValue;
  }
  return enumerable.Single();
}
public static T SingleOrDefault(此IEnumerable可枚举,T defaultValue){
如果(1!=enumerable.Count()){
返回默认值;
}
返回可枚举的.Single();
}
这可能有点贵,因为Count()需要处理整个集合,而且运行起来可能相当昂贵。最好是调用Single、捕获InvalidOperationException或滚动IsSingle方法

public static bool IsSingle<T>(this IEnumerable<T> enumerable) {
  using ( var e = enumerable.GetEnumerator() ) {
    return e.MoveNext() && !e.MoveNext();
  }
}

public static T SingleOrDefault<T>(this IEnumerable<T> enumerable, T defaultValue) {
  if ( !enumerable.IsSingle() ) {
    if( enumerable.IsEmpty() ) { 
      return defaultValue;
    }
    throw new InvalidOperationException("More than one element");
  }
  return enumerable.Single();
}
publicstaticboolissingle(此IEnumerable可枚举){
使用(var e=enumerable.GetEnumerator()){
返回e.MoveNext()&&!e.MoveNext();
}
}
公共静态T SingleOrDefault(此IEnumerable可枚举,T defaultValue){
如果(!enumerable.IsSingle()){
if(enumerable.IsEmpty()){
返回默认值;
}
抛出新的InvalidOperationException(“多个元素”);
}
返回可枚举的.Single();
}

您可以执行以下操作

myStrings.DefaultIfEmpty("myDefaultString").Single()

签出

您可以创建自己的扩展方法——SingleOrNew

public static class IEnumerableExtensions
{
    public static T SingleOrNew<T>( this IEnumerable<T> enumeration, T newValue )
    {
        T elem = enumeration.SingleOrDefault();
        if (elem == null)
        {
            return newValue;
        }
        return elem;
    }

    public static T SingleOrNew<T>( this IEnumerable<T> enumeration, Func<T,bool> predicate, T newValue )
    {
        T elem = enumeration.SingleOrDefault( predicate );
        if (elem == null)
        {
            return newValue;
        }
        return elem;
    }
}
公共静态类IEnumerableExtensions
{
公共静态T SingleOrNew(此IEnumerable枚举,T newValue)
{
T elem=enumeration.SingleOrDefault();
if(elem==null)
{
返回新值;
}
返回元素;
}
公共静态T SingleOrNew(此IEnumerable枚举、Func谓词、T newValue)
{
T elem=enumeration.SingleOrDefault(谓词);
if(elem==null)
{
返回新值;
}
返回元素;
}
}
。如果左参数为null,则计算并返回第二个参数

myCollection.SingleOrDefault() ?? new[]{new Item(...)}

这将只适用于引用类型(或空值),但它可以非常简单地完成您要查找的任务。

如果枚举包含多个对象,这将返回默认值。它不应该像标准实现那样抛出异常吗?@tvanfosson是的,它应该。我的印象是,如果存在除一个元素以外的任何元素,SingleOrDefault将返回默认值。但它显然只会在没有任何元素的情况下这样做。奇怪的是,我会更新。但这种方法的问题是,对于包含单个值为null的元素的集合,您将返回newValue参数。考虑这个表达式(new String []{NUL})。SingleOrNew(“Fo”);它会错误地返回“foo”@JaredPar——我愿意接受它。通常,我不会在我的集合中设置空值,如果我在使用这样的方法时找到空值,我可能还是想用默认值替换它。@tvanfosson,这是对原始算法的一个相当重大的突破性改变,该算法对人们如何使用null进行了大量假设。其整体思想是,当您想要保证不会得到null对象,而是得到一个填充了适当默认值的对象时,您可以使用它。我看不出有什么问题。在单元测试中包装预期的功能,以便用户清楚地了解预期的功能。如有必要,添加一些文档。我想不出一个会让我崩溃的用例。@ TvFoSon,在设计API时,你应该先考虑其他用户。在这种情况下,您提供的是对现有查询类型的重载,但从根本上改变了它的搜索方式。这可能不会让你崩溃,但会让人崩溃,这取决于你的行为。以哈希表和字典之间的差异为例。在v1中,可以为哈希表返回null,因为人们认为没有人会使用null。事实证明,这是一个非常糟糕的假设,以至于在v2A中改变了Dictionary的行为。当我开始使用null合并时,我的脑海里响起了一阵掌声+1@Joe我认为OP实际上想要更改直接从SingleOrDefault()返回的默认值,例如,如果搜索Person对象但不存在,那么他可能希望SingleOrDefault()返回NullPerson对象。我的理解是,不可能更改返回类型,问题必须以您的方式解决,但我认为再次向OP澄清SingleOrDefault()的默认返回值不能更改很重要。对于值类型的集合不起作用。例如,你找到答案了吗?您不能通过方法将默认值更改为承诺。因为SingleOrDefault应该是SingleOrNull,但它可以返回值对象。谁能告诉返回0表示整数,它是默认值还是假定值?SingleOrDefault可以返回0,但不能为默认值。返回null或not。对于OOP来说,这是一个糟糕的范例。