Linq .SingleOrDefault - 如何设置自定义类的默认值?

时间:2011-08-13 10:12:56

标签: c# linq

我回答了一些问题并搜索了谷歌, 但我找不到答案(这让我感到满意)。

基本上,我理解SingleOrDefault返回null或0(取决于类型)。

但是如何让它返回别的东西?

return myChannels.All.Where(_Channel => _Channel.Guid == this.ParentChannelGuid).SingleOrDefault(_SPECIFICCHANNEL);

所以,我希望_SPECIFICCHANNEL返回,以防它不是单身.. 可以这样做吗?

7 个答案:

答案 0 :(得分:8)

您必须制作扩展方法:

    public static T SingleOr<T>(this IEnumerable<T> list, T defaultValue) where T : class
    {
        return list.SingleOrDefault() ?? defaultValue;
    }

没有其他办法。所有类都默认为null。

答案 1 :(得分:5)

您可以使用DefaultIfEmpty()(psedo代码如下) -

return myChannels.All.Where(_Channel => _Channel.Guid == this.ParentChannelGuid).DefaultIfEmpty(_SPECIFICCHANNEL).SingleOrDefault();

答案 2 :(得分:5)

这可以通过一种相当简单的方式实现。如果您创建自己的扩展方法比通用SingleOrDefault更具体,那么编译器将更喜欢更具特定类型的版本。这是一个示例,说明如何使用简单的Person类(您可以将其复制粘贴到LINQPad以快速查看结果):

public class Person
{
    public string Name { get; set; }

    public override string ToString()
    {
        return Name ?? "";
    }
}

public static class PersonExtensionMethod
{
    public static Person SingleOrDefault(this IEnumerable<Person> source)
    {
        var person = Enumerable.SingleOrDefault(source);

        if (person == null)
            return new Person { Name = "Unnamed" };

        return person;
    }
}

public static void Main()
{
    var emptyCollection = new Person[0];
    var nonEmptyCollection = new Person[] { new Person { Name = "Jack" } };

    Debug.WriteLine("Empty collection: " + emptyCollection.SingleOrDefault());
    Debug.WriteLine("Non-empty collection: " + nonEmptyCollection.SingleOrDefault());
}

在上面的示例中,SingleOrDefault(IEnumerable<Person>)优先于SingleOrDefault<T>(IEnumerable<T>),而不是特定的。{/ p>

答案 3 :(得分:4)

  

但是如何让它返回别的东西?

你做不到。您可以创建自己的方法 - 如Oskar Kjellin所示 - 返回其他内容,但SingleOrDefault始终按编程方式运行,这意味着返回默认值(null, 0)对于一个项目。

答案 4 :(得分:3)

为什么不使用“??”运营商并说

return myChannels.SingleOrDefault(_Channel => _Channel.Guid == this.ParentChannelGuid) ??_SPECIFICCHANNEL;

答案 5 :(得分:1)

您无法定义类型的默认值。对于引用类型,它始终定义为null。对于结构体,它是结构的一个实例,其中所有成员字段依次设置为其默认值。对于枚举,它始终为0(可能是也可能不是所讨论的枚举类型的定义值)

答案 6 :(得分:0)

扩展Oskar关于扩展方法的答案,可以使它更通用,以便它可以像下面这样覆盖值和引用类型:

    public static T SingleOrSpecifiedDefault<T>(this IEnumerable<T> enumerable, Expression<Func<T, bool>> singleOrDefault, T defaultValue) where T : IComparable
    {
        T singleValue = enumerable.SingleOrDefault(singleOrDefault.Compile());
        if (singleValue == null || singleValue.CompareTo(default(T)) == 0)
        {
            return defaultValue;
        }

        return singleValue;
    }

这允许您指定与SingleOrDefaultdefaultValue(如果找不到匹配项将使用)相同的LINQ表达式。