Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq .SingleOrDefault - how to setup a default for a custom class?

Tags:

c#

linq

i went over some questions and searched google a bit, but i couldnt find an answer ( That satisfies me ).

Basicly, i understand the SingleOrDefault return null or 0 ( depends on the type ).

but how can i make it return something else ?

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

so, i want _SPECIFICCHANNEL to be returned in case it is not single.. can that be done ?

like image 380
Rafael Herscovici Avatar asked Aug 13 '11 10:08

Rafael Herscovici


People also ask

How do you use single or default?

When you want an exception to be thrown if the result set contains many records, use Single or SingleOrDefault. When you want a default value is returned if the result set contains no record, use SingleOrDefault. When you always want one record no matter what the result set contains, use First or FirstOrDefault.

What is the default value of SingleOrDefault?

The default value for reference and nullable types is null . The SingleOrDefault method does not provide a way to specify a default value. If you want to specify a default value other than default(TSource) , use the DefaultIfEmpty<TSource>(IEnumerable<TSource>, TSource) method as described in the Example section.

What is difference between single and SingleOrDefault in Linq?

The SingleOrDefault() method does the same thing as Single() method. The only difference is that it returns default value of the data type of a collection if a collection is empty, includes more than one element or finds no element or more than one element for the specified condition.

What is single and SingleOrDefault?

Single : It returns a single specific element from a collection of elements if element match found. An exception is thrown, if none or more than one match found for that element in the collection. SingleOrDefault: It returns a single specific element from a collection of elements if element match found.


3 Answers

You will have to make an extension method:

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

There is no other way. All classes default to null.

like image 118
Oskar Kjellin Avatar answered Oct 27 '22 00:10

Oskar Kjellin


This can be accomplished in a rather simple way. If you create your own extension method that is more specific than the generic SingleOrDefault, then the compiler will prefer the more type-specific version. Here's an example that shows how to do that with a simple Person class (you can copy-paste it into LINQPad to quickly see the result):

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

In the above example, SingleOrDefault(IEnumerable<Person>), takes precedence over SingleOrDefault<T>(IEnumerable<T>) which is less specific.

like image 41
Allon Guralnek Avatar answered Oct 27 '22 00:10

Allon Guralnek


Why not just use the "??" operator and say

return myChannels.SingleOrDefault(_Channel => _Channel.Guid == this.ParentChannelGuid) ??_SPECIFICCHANNEL;
like image 38
Bill Gregg Avatar answered Oct 26 '22 23:10

Bill Gregg