Изменить значение по умолчанию для класса - PullRequest
5 голосов
/ 16 июня 2011
public class MyClass
{
    public string myString;

    public MyClass(string s)
    {
        this.myString = s;
    }
}

В IEnumerable<MyClass> как изменить значение по умолчанию для метода FirstOrDefault()Например, я хочу вернуть new MyClass("HelloWorld");

Редактировать: Есть ли способ переопределить значение класса по умолчанию?Как значение по умолчанию MyClass равно new MyClass("Default");

Ответы [ 5 ]

8 голосов
/ 16 июня 2011

Вы не можете напрямую изменить это. Но у вас есть несколько альтернатив.

Если ваша последовательность не содержит null s, вы можете использовать:

MyClass result = seq.FirstOrDefault() ?? new MyClass("HelloWorld");

Или вы можете реализовать собственную версию, которая принимает параметр в качестве значения по умолчанию:

    public static T FirstOrDefault<T>(this IEnumerable<T> source, T defaultValue)
    {
        using (IEnumerator<T> enumerator = source.GetEnumerator())
        {
            if (enumerator.MoveNext())
                return enumerator.Current;
            else
                return defaultValue;
        }
    }

    public static T FirstOrDefault<T>(this IEnumerable<T> source, Func<T, bool> predicate, T defaultValue)
    {
        using (IEnumerator<T> enumerator = source.Where(predicate).GetEnumerator())
        {
            if (enumerator.MoveNext())
                return enumerator.Current;
            else
                return defaultValue;
        }
    }

Вы также можете использовать другое имя для этой реализации FirstOrDefault, но, поскольку оно не конфликтует ни с одной из существующих перегрузок, я просто использовал то же имя.

https://github.com/CodesInChaos/ChaosUtil/blob/master/Chaos.Util/LinqExtensions.cs

6 голосов
/ 16 июня 2011

В качестве эквивалентной альтернативы хорошему ответу CodeAsChaos, вы также можете сделать несколько короче:

public static T MyFirstOrDefault<T>(
    this IEnumerable<T> sequence, 
    T myDefault)
{
    foreach(T item in sequence)
        return item;
    return myDefault;
}

public static T MyFirstOrDefault<T>(
    this IEnumerable<T> sequence, 
    Func<T, bool> predicate, 
    T myDefault)
{
    return sequence.Where(predicate).MyFirstOrDefault(myDefault);
}
2 голосов
/ 25 марта 2013

Почему бы просто не использовать DefaultIfEmtpy () ?

Например:

var result = this.MyClasses
    .Where(c => c.SomeCondition)
    .Select(c => c)
    .DefaultIfEmpty(new DefaultClass())
    .First();
2 голосов
/ 16 июня 2011

Вы можете определить метод расширения следующим образом:

public static T FirstOrDefault<T>(this IEnumerable<T> source, T defaultValue)
{
    foreach (T x in source)
    {
        return x;
    }
    return defaultValue;
}
0 голосов
/ 16 июня 2011

Я собираюсь вместо использования обобщений просто привязать его к перечисляемому вашему классу:

public static MyClass FirstOrDefault(this IEnumerable<MyClass> source)
{
    foreach (var x in source)
    {
        return x;
    }
    return new MyClass("hello world"); 
    //OR, could be made a bit nicer by making a static method in your class
    return MyClass.Default();
}

Это будет делать то, что вы хотите, но только для вашего класса. Если это приемлемо, то это самый простой и короткий способ сделать это.

...