views:

128

answers:

5

I select one double value from IEnumerable, how can i overload FirstOrDefault() function, to return null on default, instead of zero, iwant something like:

double? x = from ... .FirstOrDefault();

i now i can catch exception, and write double? x = null, but i have 20 variables, and its not the way

+1  A: 

If I am understanding correctly, you could create an extension method to suit your particular purpose.

That would allow you to use the syntax:

double? d = ( linq expression ).MyCustomFirstOrNull();

http://msdn.microsoft.com/en-us/library/bb383977.aspx

See this example also for the general syntax of extension methods:

using System.Linq;
using System.Text;
using System;

namespace CustomExtensions
{
    //Extension methods must be defined in a static class
    public static class StringExtension
    {
        // This is the extension method.
        // The first parameter takes the "this" modifier
        // and specifies the type for which the method is defined.
        public static int WordCount(this String str)
        {
            return str.Split(new char[] {' ', '.','?'}, StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }
}
namespace Extension_Methods_Simple
{
    //Import the extension method namespace.
    using CustomExtensions;
    class Program
    {
        static void Main(string[] args)
        {
            string s = "The quick brown fox jumped over the lazy dog.";
            //  Call the method as if it were an 
            //  instance method on the type. Note that the first
            //  parameter is not specified by the calling code.
            int i = s.WordCount();
            System.Console.WriteLine("Word count of s is {0}", i);
        }
    }
}

http://msdn.microsoft.com/en-us/library/bb311042.aspx

Tim
can u plz give link where can i read about extensions, i dunno anything about linq
eba
general syntax is good) but nothing about linq
eba
@eba - you asked about how to "overload" the FirstOrDefault method. This is done via extension methods in .Net and isn't limited to Linq. Eric has provided a good example for your specific situation.
Tim
+7  A: 

Don't catch the exception. The purpose of the exception is to tell you that you have a bug, not to act as control flow.

It is quite straightforward to write your own extension method that does what you want, so do that:

public static double? FirstOrNull(this IEnumerable<double> items)
{
    foreach(double item in items)
        return item;
    return null;
} 

Or, if you want to be fancier about it:

public static T? FirstOrNull<T>(this IEnumerable<T> items) where T : struct
{
    foreach(T item in items)
        return item;
    return null;
} 

Make sense?

Eric Lippert
+1  A: 

I don't know what type of queries do you use. But if you work with IEnumerable you can try the following code:

double? x = (/*Some IEnumerable here*/).OfType<double?>().FirstOrDefault();

But if you care about performance you better use extension methods.

MAKKAM
Did you actually try this on a sequence of doubles? What happened?
Eric Lippert
Of course, I tried it with the List<double> and it worked exactly as expected, i.e. null for empty list and first value otherwise.
MAKKAM
+2  A: 

Why not just do:

double? x = myDoubles.Cast<double?>().FirstOrDefault();
Ani
+3  A: 

You could write following extension method, I just ripped Code of FirstOrDefault method using Reflector and amended to fit your requirements.

public static class MyExtension
{
    public static TSource? NullOrFirst<TSource>(this IEnumerable<TSource> source) where TSource : struct
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }
        IList<TSource> list = source as IList<TSource>;
        if (list != null)
        {
            if (list.Count > 0)
            {
                return list[0];
            }
        }
        else
        {
            using (IEnumerator<TSource> enumerator = source.GetEnumerator())
            {
                if (enumerator.MoveNext())
                {
                    return enumerator.Current;
                }
            }
        }
        return null;
    }
}
Int3