Reputation: 38684
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
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