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

本文关键字:设置 默认值 自定义 SingleOrDefault- Linq | 更新日期: 2023-09-27 18:05:43

我复习了一些问题,在谷歌上搜索了一下,但我找不到答案(这让我很满意(。

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

但是我怎样才能让它返回其他东西呢?

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

所以,我希望返回_SPECIFICCHANNEL,以防它不是单个的。。能做到吗?

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

您必须创建一个扩展方法:

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

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

这可以用一种相当简单的方式实现。如果您创建了比通用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>)

你能使用DefaultIfEmpty((吗(下面是psedo代码(-

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

但我如何才能让它返回其他内容

你不能。您可以制定自己的方法—如Oskar Kjellin—返回其他值,但SingleOrDefault将始终按程序运行,这意味着返回项目的默认值(null,0(。

为什么不使用"?"运算符并说

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

您不能定义类型的默认值。对于引用类型,它总是被定义为null。对于structs,它是structs的一个实例,所有成员字段依次设置为默认值。对于枚举,它总是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表达式。