What are some practical cases of why I would need something like this:
public void Show<FirstType, SecondType>(FirstType first, SecondType second)
{
//Do Something
}
And not just this:
public void Show(FirstType first, SecondType second)
{
//Do Something
}
Thanks so much
This example comes from the framework, but the LINQ extension methods are implemented this way. For example, the signature for .Where is:
IEnumerable.Where<TSource> (IEnumerable<TSource>, Func<TSource, Boolean>);
This doesn't have two type arguments like your example, but shows a good use case for having one. The "Where" is not type specific, and because the predicate given later uses the same type argument you get type safety when performing comparisons.
This far preferable to a .Where for every possible type, hence the use of generics.
Because you'll need to create another method for something like this, which might be duplication in some cases. To avoid duplicating logic, you use generics when the types have some behavior in common. Also, it's typesafe so no need to box/unbox when you use generics.
public void Show(ThirdType third, FourthType fourth)
{
//Do Something
}
I can give you a simple use of generics, for example, the method that compares two variables of the same type and returns true or false depending on the equality:
public static bool Equals<T>(T Variable1, T Variable2)
{
return Variable1.Equals(Variable2);
}
This method is now reusable for any parameter type. T stands for type and is usually written this way, but not necessarily. Using this class you can compare equality of any type you define in your main method without boxing/unboxing types inside the method. Also your equality compare method is safe from wrong type input once you use it in your main method. Example of using this method would be something like this:
public static void Main(string[] args)
{
if (VarCompare<int>(10, 10))
{
Console.WriteLine("Inputs are equal.");
}
else
{
Console.WriteLine("Inputs aren't equal.");
}
}
By simply changing your if condition to VarCompare<string>("A", "B") you could compare two string types instead of integers.
A good example of when you would want two generic parameters with different types is Dictionary<TKey, TValue>
http://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx
Related
There are several similar questions about generic methods with concrete overloads here on SO and most of them say essentially the same thing: Generic overload resolution is done at compile time so if you want to use a concrete overload, you may need to use dynamic in order to have the runtime decide which overload to use. OK, cool--I understand that. None of the questions I've found deal with an out parameter and I'm wondering if there's a better way to handle this than what I've done. Let's start with the most basic case (my code was all written and tested in LinqPad):
void Main()
{
string x = "";
var g = new GenericTest();
g.RunTest(x); //Ran from TryFoo<T>
g.RunTestWithDynamic(x);//Ran from TryFoo(string)
g.Foo(x); //Ran from TryFoo(string)
}
public class GenericTest
{
//public void RunTest(string withInput) => Foo(withInput); <-- This would fix it
public void RunTest<T>(T withInput) => Foo(withInput);
public void RunTestWithDynamic<T>(T withInput) => Foo((dynamic)withInput);
public void Foo<T>(T withInput) => Console.WriteLine("Ran from TryFoo<T>");
public void Foo(string withInput) => Console.WriteLine("Ran from TryFoo(string)");
}
Here are some things to note:
RunTest is a generic method that calls another generic method, Foo. When I call RunTest, it appears the compiler doesn't follow all the way from the call site to see that g.RunTeset is passing in x which is a string and link it all up so that the Foo(string) overload is called; instead, it just sees that RunTest<T> is calling Foo. It doesn't make different "paths" based on different input values of T. OK, that's fair and understandable.
If I call Foo directly from my Main method, the compiler is smart enough to see that we are calling Foo with a string directly and correctly selects the concrete overload.
As the linked SO posts describe, I can call RunTestWithDynamic which will change which overload is used at runtime based on value. It feels just a bit "hacky", but I'm good with this solution.
I've commented out a line: a concrete overload of RunTest. This would be essentially the same as calling Foo directly. If that were un-commented, it would fix everything. Alas, that is not an option for me in my case.
Now, what if the T is for an out parameter? Consider the pattern used by, say, int.TryParse where you return a bool to indicate if it succeeded or not, but the value you actually want is an out. Now you can't really do dynamic resolution because you can't cast an out parameter. I considered doing something where I make a default(T) and then casting that to dynamic, but if that ever works well anywhere else, there is the problem of reference types that default to null to deal with. Nope, that doesn't work, either.
In the end, the best I could come up with was this:
void Main()
{
string x;
var g = new GenericTest();
g.TryRunTest(out x); //Ran from TryFoo<T>
g.TryRunTestWithDynamic(out x); //Ran from TryFoo(string)
g.TryFoo(out x); //Ran from TryFoo(string)
}
public class GenericTest
{
//This would fix it, but in my case, not an option
//public bool TryRunTest(out string withOutput) => return TryFoo(out withOutput);
public bool TryRunTest<T>(out T withOutput)
{
return TryFoo(out withOutput);
}
public bool TryRunTestWithDynamic<T>(out T withOutput)
{
if(typeof(T) == typeof(string))
{
var retval = TryFoo(out string s);
withOutput = (T)(dynamic)s;
return retval;
}
return TryFoo(out withOutput);
}
public bool TryFoo<T>(out T withOutput)
{
withOutput = default(T);
Console.WriteLine("Ran from TryFoo<T>");
return true;
}
public bool TryFoo(out string withOutput)
{
withOutput = "Strings are special";
Console.WriteLine("Ran from TryFoo(string)");
return true;
}
}
You can see that TryRunTestWithDynamic has to look for the concrete string type specifically. I can't figure out a way to do it so that I can just add overloads and then use dynamic resolution to select the overload I want without having to spell it all out (and let's face it--spelling it all out kind of kills the whole point of having overloads in the first place).
In his post I linked to above (and here for good measure), Jon Skeet mentions using MethodInfo.MakeGenericMethod as an alternative. Here he talks about how to use it. I'm curious if that would help me here, but I can't figure out how to use it with out parameters.
So, here are my specific questions:
While, yes this DOES work, it is VERY clunky. Is there a better way to do this? Most importantly, is there a way I can consume overloads that wouldn't require me checking each type specifically?
Is there a way to use the MethodInfo.MakeGenericMethod route using out parameters and would that help me?
Let's say we could wave a magic wand and all of a sudden a language feature was added to C# that would give us the option to force dynamic resolution for generic methods (either for all cases, or only for the case where the generic parameter is for an out, like my main problem). Taking from the above examples, let's say we had something like this:
//The following are all invalid syntax but illustrate possible
// ways we may express that we want to force dynamic resolution
//For out parameters
public void TryFoo<T>(dynamic out T withOutput){...}
//"dynamic out" could be a special combination of keywords so that this only works
// with output variables. Not sure if that constraint buys us anything.
// Maybe we would want to allow it for regular (not out) generic parameters as well
public void Foo<T>(dynamic T withInput){...}
public void Foo<dynamic T>(T withInput){...}
public void dynamic Foo<T>(T withInput){...}
Let's not focus on the syntax itself; we could easily use a different notation--that isn't the point. The idea is simply that we are telling the runtime that when we get to TryFoo<T>... pause and check to see if there is a different, better fitting overload that we should switch to instead. I'm also not particular on whether we are checking for a better resolution on T specifically, or if it applies to the method in general.
Is there any reason why this might be a BAD thing? As he often does, Eric Lippert makes some interesting points about generic and concrete overloading resolution when inheritance is involved (Jon Skeet is also quoted in other answers, as well) and discusses why choosing the most specific overload isn't always the best choice. I'm wondering if having such a language construct might introduce similar problems.
OK, so I proposed the idea of adding support for opting-in to dynamic binding at the C# GitHub and was given this alternate solution which I like MUCH better than what I am currently doing: ((dynamic)this).TryFoo(out withOutput);
It would look like this:
public bool TryRunTestWithDynamic<T>(out T withOutput)
{
return ((dynamic)this).TryFoo(out withOutput);
}
I will reiterate the warning I was given: this only works for instance methods. In my case, that's fine, but if someone else had a method that was static, it wouldn't help, so the second part of my question (regarding MethodInfo.MakeGenericMethod) may still be relevant.
I was surprised today by the way the method resolution works.
Here's the code as an exemple :
class Program
{
static class Mapper<TSource, TTarget>
{
public static void Map<TMember>(Expression<Func<TSource, TMember>> source, Expression<Func<TTarget, TMember>> target)
{
Console.WriteLine("A");
}
public static void Map<TMember, TSourceCollection>(Expression<Func<TSource, TSourceCollection>> source, Expression<Func<TTarget, TMember[]>> target)
where TSourceCollection : IEnumerable<TMember>
{
Console.WriteLine("B");
}
}
class A
{
public byte[] prop { get; set; }
}
class B
{
public byte[] prop { get; set; }
}
static void Main(string[] args)
{
Mapper<A, B>.Map(x => x.prop, x => x.prop);
}
}
As you see the method Map has two overloads, one when the type of the properties are the same, and one when the source property is an enumerable and the right property is an array.
Then when i call the method with an array on both sides it calls the second overload, but as the types are exactly the same i expected the first overload to be called.
I thought the first overload would have a better scoring because it depends on fewer generic arguments than the second, and it fits better with the types of the arguments i pass to the method.
Can someone explain why the compiler chooses to call the second overload instead of the first one please ?
Thanks.
Overload resolution is complicated and you can read the spec to understand why. One thing I am pretty sure of though is that it doesn't consider the need to specify less generic parameters when considering which overload is better (though it will take non-generic over generic but when both are generic it considers them equal).
When looking at the overloads it can choose from they are all equal apart from whether the second parameter is TMember or TMember[].
The spec talks a lot about choosing the most specific member and I can't work out which part is actually applicable here (there are many places where it talks about preferring X over Y when X is more specific). I would have thought it was either Section 7.6.5.1 (of the c#5 spec) which is where it constructs a candidate list or section 7.5.3 where it deals with overload resolution. However the former doesn't seem to exclude either method overload and the latter to my reading only deals with the parameters after the generic ones have been substituted in at which point they are identical. It may be that there is somewhere else in the spec that deals with this (eg when it infers the type arguments).
In woolly terms though I believe that the compiler is considering that TMember[] is more specific than TMember. This can be broadly seen to be true because TMember will accept more things than TMember[] will so TMember[] is more specific.
The matching of first method TMember and second method TSourceCollection is of equal value for any type that satisfies the where TSourceCollection : IEnumerable<TMember> condition.
The type TMember[] is a more detailed type match for byte[] compared to TMember. So this should be the point where the second method scores better than the first. Consequently, this 'better' match outrules the fact, that method two has more generic parameters.
I am fairly new to C# and I am trying to create a generic extension method that that takes any enumeration as the parameter. Based on the enumeration I want to retrieve an attribute that has been applied within the enumeration. I want to be able to use this extension method across multiple enumerations. I currently only have the static method directly in my class that contains the enumeration and it looks like this:
public static string GetIDForEnum(Enum enum)
{
var item = typeof(Enum).GetMember(enum.ToString());
var attr = item[0].GetCustomAttribute(typeof(DescriptionAttribute), false);
if(attr.Length > 0)
return ((DescriptionAttribute)attr[0]).Description;
else
return enum.ToString();
}
How do I make this a generic extension method?
How do I make this a generic extension method?
You can't, at the moment... because C# doesn't allow you to constrain a type parameter to derive from System.Enum. What you want is:
public static string GetIdForEnum<T>(T value) where T : Enum, struct
... but that constraint is invalid in C#.
However, it's not invalid in IL... which is why I created Unconstrained Melody. It's basically a mixture of:
A library with useful generic delegate and enum methods
A tool to run ildasm and ilasm to convert permitted constraints into the ones we really want
You could do something similar yourself - but it's all a bit hacky, to be honest. For enums it does allow an awful lot more efficient code though...
Class StudentFeeCollection
{
public static bool CheckAdmissionMonth(int AdmissionNo)
{
}
public static DataTable CheckAdmissionMonth(int AdmissionNo)
{
}
}
Is this possible or not, please tell me.
You can use out parameter:
class StudentFeeCollection
{
public static void CheckAdmissionMonth(int AdmissionNo, out bool result)
{
........
}
public static void CheckAdmissionMonth(int AdmissionNo, out DataTable tbl)
{
.......
}
No, that's not possible. You need to make sure that the signature of each overload is unique.
From the documentation:
Changing the return type of a method does not make the method unique as stated
in the common language runtime specification. You cannot define overloads that
vary only by return type.
Reference:
http://msdn.microsoft.com/en-us/library/vstudio/ms229029(v=vs.100).aspx
This is not possible. Imagine you're the compiler or the runtime--how would you know which return type the code was asking for? If you really need to support returning multiple datatypes from a method, using generics is your best bet. That said, looking at your specific example, I suggest not doing it here. Having one method that returns either a boolean or a DataTable seems like a pretty shoddy design.
You can overload by argument types in c# but not by return type.
As Arshad said you can use out/ref parameters since these are arguments and not return types.
Also you can't overload by generic constraints of arguments(say having 2 versions where one is a struct and another is a class). see https://msmvps.com/blogs/jon_skeet/archive/2010/10/28/overloading-and-generic-constraints.aspx
one reason to avoid return type overloading, from the c++ language description:
The reason is to keep resolution for an individual operator or function call context-independent.
note: in some programming language like haskell you can overload by return types
see Function overloading by return type? for more info
I have a method that logs out data, and takes bunch of inputs using the params keyword
public static void LogData<T>(params object[] parameter)
{
// log out the data
}
I'd like to restrict the inputs to strings and numeric types, and my first thought was to use a where clause. The obvious issue with this are that you can't use concrete types in a where clause, but you can get around this by noticing that both string and numeric types are IComparable and IConvertible. I thought this might help:
public static void LogData<T>(params T[] parameter)
where T : IComparable, IConvertible
{
// log out the data
}
This doesn't work because then all the inputs have to be one type.
Is there a way to restrict the inputs to string and numeric types using the params keyword or some other syntax?
I'm not sure why you want to do that, when every object has a ToString method.
Anyway, you can declare a new class - NumberOrString that will support implicit conversions from a string and the numeric types you want to support. Then have your LogData method accept a params NumberOrString[] p
Consiidering you are talking about strings and numeric types, it's not possible. If condition would be or, you can define an optional parameter of type List<T> where T is any chosen numeric type.
I'd create multiple methods which are essentially overloads using the types I want to support.
might be too much code and repetitive but the basic "log out the data" routine would essentially be reused across all overloads.
Here's one potential solution:
public static void LogData(params IConvertible[] parameter)
{
// log out the data
}
Although I wonder if there's actually any reason you need the objects to be IComparable or IConvertible, or if you'd just like to restrict them to known types (i.e. strings or numbers). I think zmbq's answer might be the way to go. Or you might even really just want to see if the object implements a useful ToString method. Here's a way to find that out (not a compile-time restriction, as you might expect, but at runtime using reflection).