David.Chu.ca
David.Chu.ca

Reputation: 38684

Question about var type

I am new to C# 3.0 var type. Here I have a question about this type. Take the following simple codes in a library as example:

 public class MyClass {
    public var Fn(var inValue)
    {
        if ( inValue < 0 )
        {
           return 1.0;
        }
        else 
        { 
           return inValue;
        }
    }
 }

I think the parameter is an anonymous type. If I pass in a float value, then the Fn should return a float type. If a double value type is passed in, will the Fn return a double type? How about an integer value type as input value?

Actually, I would like to use var type with this function/method to get different return types with various input types dynamically. I am not sure if this usage is correct or not?

Upvotes: 0

Views: 214

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1503290

You can't use var for return values or parameter types (or fields). You can only use it for local variables.

Eric Lippert has a blog post about why you can't use it for fields. I'm not sure if there's a similar one for return values and parameter types. Parameter types certainly doesn't make much sense - where could the compiler infer the type from? Just what methods you try to call on the parameters? (Actually that's pretty much what F# does, but C# is more conservative.)

Don't forget that var is strictly static typing - it's just a way of getting the compiler to infer the static type for you. It's still just a single type, exactly as if you'd typed the name into the code. (Except of course with anonymous types you can't do that, which is one motivation for the feature.)

EDIT: For more details on var, you can download chapter 8 of C# in Depth for free at Manning's site - this includes the section on var. Obviously I hope you'll then want to buy the book, but there's no pressure :)

EDIT: To address your actual aim, you can very nearly implement all of this with a generic method:

public class MyClass
{
    public T Fn<T>(T inValue) where T : struct
    {
        Comparer<T> comparer = Comparer<T>.Default;
        T zero = default(T);
        if (comparer.Compare(inValue, zero) < 0)
        {
            // This is the tricky bit.
            return 1.0;
        }
        else 
        { 
            return inValue;
        }
    }
}

As shown in the listing, the tricky bit is working out what "1" means for an arbitrary type. You could hard code a set of values, but it's a bit ugly:

public class MyClass
{
    private static readonly Dictionary<Type, object> OneValues
        = new Dictionary<Type, object>
    {
        { typeof(int), 1 },
        { typeof(long), 1L },
        { typeof(double), 1.0d },
        { typeof(float), 1.0f },
        { typeof(decimal), 1m },
    };

    public static T Fn<T>(T inValue) where T : struct
    {
        Comparer<T> comparer = Comparer<T>.Default;
        T zero = default(T);
        if (comparer.Compare(inValue, zero) < 0)
        {
            object one;
            if (!OneValues.TryGetValue(typeof(T), out one))
            {
                // Not sure of the best exception to use here
                throw new ArgumentException
                    ("Unable to find appropriate 'one' value");
            }
            return (T) one;
        }
        else 
        { 
            return inValue;
        }
    }
}

Icky - but it'll work. Then you can write:

double x = MyClass.Fn(3.5d);
float y = MyClass.Fn(3.5f);
int z = MyClass.Fn(2);

etc

Upvotes: 9

John Sheehan
John Sheehan

Reputation: 78152

You cannot use var as a return type for a method.

Upvotes: 5

Related Questions