Generic version vs interface version of a method - c#

What is the difference between these two methods?
first:
public static int Foo<T>(T first, T second) where T:IComparable
{
return first.CompareTo(second)
}
second:
public static int Foo(IComparable first, IComparable second)
{
return first.CompareTo(second);
}

For the first method, the types of the two parameters have to be same, e.g., int and int. The type has to implement the IComparable interface.
For the second method, the two parameters can have different types. Both types must implement the IComparable interface, but do not have to be the same, e.g., int and string.
Note that the IComparable.CompareTo method will likely throw an exception if the types are not the same. So it's better to make sure that the types are actually the same. You can do this by using your first method, or even better by using the generic IComparable<T> interface.
The follow-up question is, of course: What is the difference between these two methods?
first:
public static int Foo<T1, T2>(T1 first, T2 second) where T1 : IComparable<T2>
{
return first.CompareTo(second);
}
second:
public static int Foo<T>(IComparable<T> first, T second)
{
return first.CompareTo(second)
}
Answer: The first method doesn't box the first argument, while the second method does.

From the code fragment provided the difference that can say, that
Generics version:
for generics new code will be generated for every type defined
Foo<Class1>, Foo<Class2>, Foo<Class3>.
you need to define a type at compile time
Interface version:
benefit from OOP concepts, hiding implementation details from the actual code.
runtime type definiton (more flexibility), but less "generic" in terms of pure sence of that word.
In general: interface version is more flexible but less generic (everything, by the way, depends naturally on concrete code implementaiton).

Related

C#: Non-generic interfaces w/generic methods, generic implementation… (compile time) type safety?

There probably are threads here that explain it, but my google fu seems not to be good enough to find them.
I have a pretty common problem: I want to have a non-generic interface that I can put in some kind of enumerable, but ONE of the interface's methods will have a generic input parameter, but as an input parameter, its type is inferable.
For various reasons, I want my implementation to be generic, because the input parameter mentioned above is being used in a few more places in the implementation, among others as type of a property.
Let me give you an example of how it might be implemented to make clearer what I mean:
public interface IThreshold
{
/* various (non-generic) methods and properties */
bool ThresholdExceeded<T>(T value) where T : IComparable<T>, IEquatable<T>;
}
public class Threshold<T> : IThreshold where T : IComparable<T>, IEquatable<T>
{
/* various (non-generic) methods and properties */
T ThresholdValue { get; }
bool IThreshold.ThresholdExceeded<U>(U value) where U : IComparable<U>, IEquatable<U> => ThresholdExceeded((T)(object)value);
public bool ThresholdExceeded(T value)
{
// ...
}
}
[…]
((IThreshold)thresholdOfIntInstance).ThresholdExceeded(5) ? DoSomething();
This will work (unless I introduced an error when simplifying it for the example), however, type safety is of course out the window with the (T)(object)value cast.
Of course I'd rather have a compile time type check than a possible runtime InvalidCastException.
But at the same time, I can't simply use my implementation's T as the ThresholdExceeded input type, since
if I leave out the IThreshold.ThresholdExceeded<U>, it will not recogise ThresholdExceeded(T value) as the implementation of the interface method (of course, the T isn't the same to the compiler)
if I change the constraints for IThreshold.ThresholdExceeded<U> to where U : IComparable<U>, IEquatable<U>, T or something similar, the compiler complains that the constraints in the implementation don't match the interface anymore (I wonder why, since they're only stricter, but ah well)
Is there a pattern that allows me to implement this in a way to keep both compile time type checking AND the comfort of calling the interface method with any kind of type without casting to a specific implementation first (and, of course, while keeping the interface itself non-generic, so that I can have multiple generic instances in an IEnumerable and call the method on them without casting them first)?

Two methods with same name but different generic parameters [duplicate]

UPDATE: As of C# 7.3, this should no longer be an issue. From the release notes:
When a method group contains some generic methods whose type arguments do not satisfy their constraints, these members are removed from the candidate set.
Pre C# 7.3:
So I read Eric Lippert's 'Constraints are not part of the signature', and now I understand that the spec specifies that type constraints are checked AFTER overload resolution, but I'm still not clear on why this MUST be the case. Below is Eric's example:
static void Foo<T>(T t) where T : Reptile { }
static void Foo(Animal animal) { }
static void Main()
{
Foo(new Giraffe());
}
This doesn't compile because overload resolution for: Foo(new Giraffe()) infers that Foo<Giraffe> is the best overload match but then the type constraints fail and a compile-time error is thrown. In Eric's words:
The principle here is overload resolution (and method type inference) find the best possible match between a list of arguments and each candidate method’s list of formal parameters. That is, they look at the signature of the candidate method.
Type constraints are NOT part of the signature, but why can't they be? What are some scenarios where it is a bad idea to consider type constraints part of the signature? Is it just difficult or impossible to implement? I'm not advocating that if the best chosen overload is for whatever reason impossible to call then silently fallback to the second best; I would hate that. I'm just trying to understand why type constraints can't be used to influence the choosing of the best overload.
I'm imagining that internally in the C# compiler, for overload resolution purposes only (it doesn't permanently rewrite the method), the following:
static void Foo<T>(T t) where T : Reptile { }
gets transformed to:
static void Foo(Reptile t) { }
Why can't you sort of "pull in" the type constraints into the formal parameter list? How does this change the signature in any bad way? I feel like it only strengthens the signature. Then Foo<Reptile> will never be considered as an overload candidate.
Edit 2: No wonder my question was so confusing. I didn't properly read Eric's blog and I quoted the wrong example. I've edited in the example I think more appropriate. I've also changed the title to be more specific. This question doesn't seem as simple as I first imagined, perhaps I'm missing some important concept. I'm less sure that this is stackoverflow material, it may be best for this question/discussion to be moved elsewhere.
The C# compiler has to not consider type constraints as part as the method signature because they are not part of the method signature for the CLR. It would be disastrous if the overload resolution worked differently for different languages (mainly due to the dynamic binding that may happen at runtime and should not be different from one language to another, or else all hells would break loose).
Why was it decided that these constraints would not be part of the method signature for the CLR is another question alltogether, and I could only make ill informed suppositions about that. I'll let the people in the know answer that.
If T matches multiple constraints, you create an ambiguity that cannot be automatically resolved. For example you have one generic class with the constraint
where T : IFirst
and another with the constraint
where T : ISecond
You now want T to be a class that implements both IFirst and ISecond.
Concrete code example:
public interface IFirst
{
void F();
}
public interface ISecond
{
void S();
}
// Should the compiler pick this "overload"?
public class My<T> where T : IFirst
{
}
// Or this one?
public class My<T> where T : ISecond
{
}
public class Foo : IFirst, ISecond
{
public void Bar()
{
My<Foo> myFoo = new My<Foo>();
}
public void F() { }
public void S() { }
}

Difference between generic constraint and superclass/interface [duplicate]

What is the difference between this:
void MyMethod(IMyInterface value)
{
//...
}
and this:
void MyMethod<T>(T value) where T : IMyInterface
{
//...
}
The main functional difference is that you can know the actual type of the object inside of the generic method. The T parameter will contain the actual type which can advantageous in certain scenarios.
In the non-generic case you cannot guarantee access to the underlying type of the object. Most of the type you could grab value.GetType() but the user could pass Null and thwart you.
Jared has mentioned some of the points; another interesting one: with generics, you can avoid boxing of value-types as long as you basically don't touch it... so I could have a struct Foo : IMyInterface and pass it in, and it won't get boxed.
The difference gets more noticeable with things like collections:
static void Foo(IEnumerable<IMyInterface> data) {}
vs
static void Foo<T>(IEnumerable<T> data)
where T : IMyInterface {}
Now, since C# 3.0 doesn't have covariance (except for arrays), I can't pass a List<Bar> to the top one, even if Bar : IMyInterface - but I can with the second (implicit T = Bar).
The generic version will require .NET 2.0.
But seriously, while they look similar, there are fundamental differences between them. One difference is, at runtime, the JIT compiler will generate code for each value type that will be used for the generic version. The non-generic version will require the value types to be boxed in order to be passed to the function.
The difference will also matter when dealing with delegates. The signature of MyMethod<int> matches void MyDelegate(int x) while the non-generic version is not matched.
Another difference, using the generic method allows you to specify multiple interfaces that your object must implement:
class Dictionary<TKey,TVal>
where TKey: IComparable, IEnumerable
where TVal: IValue
{ ... }
Another subtle difference is that you can't overload a method only on constraints (constraints aren't part of the signature of the method):
This is illegal:
void MyMethod<T>(T value) where T : IMyInterface
{
//...
}
void MyMethod<T>(T value) where T : IMyInterface2
{
//...
}
while this is legal:
void MyMethod(IMyInterface value)
{
//...
}
void MyMethod(IMyInterface2 value)
{
//...
}
Another caveat to consider with this scenario is the fact that using "where T : <%your base interface or abstraction%>" can be overused in generics rendering your generic type non-generic in nature.
IE: Remember that by isolating your generic method to IMyInterface, you're isolating that method to only those types implementing IMyInterface. So if you've merely chosen to use IMyInterface based on good OOP principles, but you have only one (or in some cases a very small number of) potential type anywhere that'll be implementing that interface, then you've defeated the purpose of using generics. Under that circumstance, the first option would be better.
Only use "where" on your generic type when you're going to have a broader range of types that actually implement IMyInterface.
Yet another difference for generic methods in general (though not for your example) is that if one has a method like T MungeThing<T>(T it) where T:IMungeable<T> and class Fnord implements IMungeable<Fnord>, then code will be able to say: Fnord thing1, thing2; ... thing1 = MungeThing(thing2); and the compiler will know that MungeThing will return a Fnord rather than some arbitrary implementation of IMungable.

Generic constraints

Which version is better:
using System;
namespace Utils.Extensions
{
public static class EnumerableExtensions
{
public static bool Between<T>(this T item, T min, T max) where T : IComparable<T>
{
return item.CompareTo(min) >= 0 && item.CompareTo(max) <= 0;
}
}
}
or
using System;
namespace Utils.Extensions
{
public static class EnumerableExtensions
{
public static bool Between<T>(this IComparable<T> item, T min, T max)
{
return item.CompareTo(min) >= 0 && item.CompareTo(max) <= 0;
}
}
}
I think both should work, but which one should I use?
Note that using the second version when T is a value-type means that item will be boxed. Casting a value-type to an interface always requires boxing.
I wouldn't worry too much about this for interfaces in general, but it's worth noting that almost every IComparable<T> implementation in the BCL is a value-type. Only you can decide whether the (small) boxing overhead is acceptable.
I think the second one is better. It won't clutter up intelliSense suggestion list for types that are not IComparable. (It won't in any case.)
And what you are looking for is specific to IComparable.
So, it is clear enough to use the second approach if what you are opting for is readability.
There's an obvious difference between the two. The first one is expected to be used on a type that implements IComparable<T>, where the second one is meant to be use on an IComparable<T>.
Given example A:
IComparable<int> x = 14;
bool y = x.Between(12, 23);
Contrast to example B:
int x = 14;
bool y = x.Between(12, 23);
If you attempt to use example A with your first technique (the generic constraint), then you are going to get a compiler error, because the constraint requires a type that implements IComparable<int>, and not an IComparable<int> itself.
Example B will compile using both techniques. I would advise using the second technique so that it works the same in both situations. It appears to be the convention anyway, probably for this reason. But there are other reasons to avoid using the first one anyway. In situations where you might wish to overload a method for particular types, the second method gives you more flexibility.
I would say the first one, because it says something about every T, where the second one only says that item should be IComparable. Indeed it should do the same, but by means of what you want to say, that every T is IComparable. The first one is better.

Generic methods and method overloading

Method overloading allows us to define many methods with the same name but with a different set of parameters ( thus with the same name but different signature ).
Are these two methods overloaded?
class A
{
public static void MyMethod<T>(T myVal) { }
public static void MyMethod(int myVal) { }
}
EDIT:
Shouldn't statement A<int>.MyMethod(myInt); throw an error, since constructed type A<int> has two methods with the same name and same signature?
Are the two methods overloaded?
Yes.
Shouldn't statement A<int>.MyMethod(myInt); throw an error, since constructed type A<int> has two methods with the same signature?
The question doesn't make sense; A is not a generic type as you have declared it. Perhaps you meant to ask:
Should the statement A.MyMethod(myInt); cause the compiler to report an error, since there are two ambiguous candidate methods?
No. As others have said, overload resolution prefers the non-generic version in this case. See below for more details.
Or perhaps you meant to ask:
Should the declaration of type A be illegal in the first place, since in some sense it has two methods with the same signature, MyMethod and MyMethod<int>?
No. The type A is perfectly legal. The generic arity is part of the signature. So there are not two methods with the same signature because the first has generic arity zero, the second has generic arity one.
Or perhaps you meant to ask:
class G<T>
{
public static void M(T t) {}
public static void M(int t) {}
}
Generic type G<T> can be constructed such that it has two methods with the same signature. Is it legal to declare such a type?
Yes, it is legal to declare such a type. It is usually a bad idea, but it is legal.
You might then retort:
But my copy of the C# 2.0 specification as published by Addison-Wesley states on page 479 "Two function members declared with the same names ... must have have parameter types such that no closed constructed type could have two members with the same name and signature." What's up with that?
When C# 2.0 was originally designed that was the plan. However, then the designers realized that this desirable pattern would be made illegal:
class C<T>
{
public C(T t) { ... } // Create a C<T> from a given T
public C(Stream s) { ... } // Deserialize a C<T> from disk
}
And now we say sorry buddy, because you could say C<Stream>, causing two constructors to unify, the whole class is illegal. That would be unfortunate. Obviously it is unlikely that anyone will ever construct this thing with Stream as the type parameter!
Unfortunately, the spec went to press before the text was updated to the final version. The rule on page 479 is not what we implemented.
Continuing to pose some more questions on your behalf:
So what happens if you call G<int>.M(123) or, in the original example, if you call A.MyMethod(123)?
When overload resolution is faced with two methods that have identical signatures due to generic construction then the one that is generic construction is considered to be "less specific" than the one that is "natural". A less specific method loses to a more specific method.
So why is it a bad idea, if overload resolution works?
The situation with A.MyMethod isn't too bad; it is usually pretty easy to unambiguously work out which method is intended. But the situation with G<int>.M(123) is far worse. The CLR rules make this sort of situation "implementation defined behaviour" and therefore any old thing can happen. Technically, the CLR could refuse to verify a program that constructs type G<int>. Or it could crash. In point of fact it does neither; it does the best it can with the bad situation.
Are there any examples of this sort of type construction causing truly implementation-defined behaviour?
Yes. See these articles for details:
https://ericlippert.com/2006/04/05/odious-ambiguous-overloads-part-one/
https://ericlippert.com/2006/04/06/odious-ambiguous-overloads-part-two/
Yes. MyMethod(int myVal) will be called when the type of the parameter is an int, the generic overload will be called for all other parameter arguments, even when the parameter argument is implicitly convertible to (or is a derived class of) the hardcoded type. Overload resolution will go for the best fit, and the generic overload will resolve to an exact match at compile time.
Note: You can explicitly invoke the generic overload and use an int by providing the type parameter in the method call, as Steven Sudit points out in his answer.
short s = 1;
int i = s;
MyMethod(s); // Generic
MyMethod(i); // int
MyMethod((int)s); // int
MyMethod(1); // int
MyMethod<int>(1); // Generic**
MyMethod(1.0); // Generic
// etc.
Yes, they are. They will allow code as such:
A.MyMethod("a string"); // calls the generic version
A.MyMethod(42); // calls the int version
Yes, they are overloaded. The compiler is supposed to prefer explicit method signatures against generic methods if they are available. Beware, however, that if you can avoid this kind of overload you probably should. There have been bug reports with respect to this sort of overload and unexpected behaviors.
https://connect.microsoft.com/VisualStudio/feedback/details/522202/c-3-0-generic-overload-call-resolution-from-within-generic-function
Yes. They have the same name "MyMethod" but different signatures. The C# specification, however, specifically handles this by saying that the compiler will prefer the non-generic version over the generic version, when both are options.
Yes. Off the top of my head, if you call A.MyMethod(1);, it will always run the second method. You'd have to call A.MyMethod<int>(1); to force it to run the first.

Categories