Here's what I am trying to write:
public void Foo<T>(T parameter) {
otherObject.Bar<T>(parameter);
}
The signature of the Bar() method is:
public void Bar<T>(T parameter) where T: class
So I get a compile error because the T in Foo's signature doesn't have the same constraint. Unfortunately I can't write:
public void Foo<T>(T parameter) where T: class {
otherObject.Bar<T>(parameter);
}
because Foo is implementing a method defined in an external interface. Question is:
Can I somehow transpose the T within the method Foo before calling Bar. (Note, I can be sure that T always will be a class - I just need to get past the compiler).
The only way I have found is using reflection but I wonder if there is a simpler trick I'm missing.
You can use the dynamic keyword like this:
public void Foo<T>(T parameter)
{
dynamic p = parameter
otherObject.Bar(p);
}
What's happening is that the resolution of the call to otherObject.Bar is being made at run-time, because one of the parameters has a type of dynamic. Assuming that T is a reference type, the resolution will succeed.
Granted, this ultimately uses reflection (as you've indicated), but the syntax is probably better than what you're using.
Of course, this will give you a run-time error in the event that T is not a class.
public void Foo<T>(T parameter)
{
otherObject.Bar<object>(parameter);
}
Here's a slightly different take on casperOne's answer, using implicit interface implementation:
public void Foo<T>(T parameter) where T: class {
otherObject.Bar<T>(parameter);
}
void IFoo.Foo<T>(T parameter){
Foo((dynamic)parameter);
}
This allows you to include the constraint on anything that knows what specific object type they're calling .Foo on at compile time, while still allowing you to implement the IFoo interface.
If you are the owner of otherObject.Bar, could you not just remove the class constraint? of that method. Or create a new similar method without the constraint?
casperOne. I am not sure your answer is correct, as you have the class constraint on your Foo method. The question stated that this was not possible as Foo was an implementation of an external interface. For instance, the code below does not work.
public void Foo<T>(T param)
{
dynamic xx = param;
this.Bar(param);
}
private void Bar<T>(T param) where T: class {
}
And shows up as an error.
Related
Is any difference between :
public void Method1<T>(class1 c, T obj) where T:Imyinterface
And
public void Method2(class1 c, Imyinterface obj)
?
What are the benefits of use the first one method?
As noted, with void methods, there is not much difference in usage.
If you look behind the scenes you will see that with the generic method, .NET will compile a separate method for each type you call it with. This has the effect of avoiding boxing when called with a struct.
The big difference occurs when you use a return type.
public T Method1<T>(class1 c, T obj) where T: IMyInterface
and
public IMyinterface Method2(class1 c, IMyInterface obj)
With the generic version, you get the original type back, so you can continue calling properties or methods (instance or extension) on the original type.
With the non-generic version, you only get back a value of type IMyInterface, so you can only call properties or methods that are part of IMyInterface.
This is most interesting, in my book, when used with extension methods and a fluent-style API.
public static T Move<T>(this T animal) where T : ICanMove
{
return animal;
}
public static T Fly<T>(this T animal) where T : ICanFly
{
return animal;
}
public static T Pounce<T>(this T animal) where T : ICanPounce
{
return animal;
}
Given that Tiger implements ICanMove and ICanPounce and the Eagle implements ICanMove and ICanFly, I can call the above extension methods that apply to the original type. Intellisense will show .Fly() and .Move() available for an Eagle, and .Pounce() and a .Move() for a Tiger.
var birdie = new Eagle();
birdie
.Move()
.Fly()
.Move()
.Fly();
var kitty = new Tiger();
kitty
.Move()
.Pounce()
.Move()
.Pounce();
Here is what it would look like if you implemented Move non-generically:
public static ICanMove Move<T>(this ICanMove animal)
{
return animal;
}
Since an ICanMove interface is returned, the compiler has no idea that it was originally an Eagle or a Tiger, and so you can only use extensions, methods, or properties that are part of the ICanMove interface.
Using a generic method gives you various possibilities with slight signature changes:
public void Method1<T>(class1 c, T obj) where T:Imyinterface, new():
This allows to instantiate new instances of type T.
public T Method1<T>(class1 c, T obj) where T:Imyinterface:
This allows you to use the method without casting it's return value when needed.
public void Method1<T>(class1 c, ref T obj) where T:Imyinterface:
This allows you to assing a new value to obj's reference. Same applies to out.
These are impossible with the non generic version.
While in your scenario it's practically the same (except for the fact that with method accepting interface parameter it will upcast concrete object to interface type) consider slightly different scenario. Let's say we want our method to accept only class that implements two interfaces IMyInterface1 and IMyInterface2 and that otherwise code should not compile :
interface IMyInterface1 { }
interface IMyInterface2 { }
class MyClass : IMyInterface1 { }
public void Method1<T>(Class1 c, T obj) where T : IMyInterface1, IMyInterface2
{
}
If we create method that accepts interface as it's second parameter it will not satisfy the condition because it doesn't restrict user from sending class instance that implements only one interface but doesn't implements the second interface like it is for MyClass and IMyInterface2 in this example.
And what interface should user send ? He don't really know the type that needs to send on compile-time.
This is a good spot to use generic and generic constrains and on the other hand we cannot use single interface parameter.
There is no big difference for void methods.
public void Method1<T>(class1 c, T obj) where T : Imyinterface
equals to
public void Method2(class1 c, Imyinterface obj, Type t)
where t must be Imyinterface.
So if you need to pass some Type to your method, and you need to apply some constraints to that Type at compile-time, use the generic method.
I've been a little puzzled with Delegates and Generic Methods.
Is it possible to assign a delegate to a method with a generic type parameter?
I.E:
//This doesn't allow me to pass a generic parameter with the delegate.
public delegate void GenericDelegate<T>()
someDelegate = GenericMethod;
public void GenericMethod<T>() where T : ISomeClass
{
}
I'm trying to pass this delegate into the function with a generic type of the interface that the method is expecting, with a function like this:
void CheckDelegate(GenericDelegate<ISomeClass> mechanism);
so that I can use the delegate like so:
someDelegate<ImplementsSomeClass>();
Your question makes no sense because you can't ever use an open generic type to declare a storage location (like a local variable or field). It must always be closed.
I understand you want to pass a GenericDelegate<T> to a method taking such a value as an argument. But even then the delegate type becomes closed with T as the generic type parameter.
In your sample code you write
someDelegate = GenericMethod;
but what type is someDelegate supposed to have? It must either be obviously closed (GenericDelegate<string>) or closed with a generic type parameter from the outer scope:
void SomeOuterMethod<T>() where T : ISomeClass {
GenericDelegate<T> someDelegate = GenericMethod<T>;
}
I hope I understood your problem. If not, please clarify. If you elaborate a little on what you want to accomplish I'll try to suggest a practical solution.
Other languages like Haskell do have support for passing around values of open generic types (in other words, you can have a variable of type IEnumerable<>). This is required to implement monads. The CLR does not have that feature.
New thought: instead of a delegate you could create a non-generic base type with a generic method that can be overridden:
interface CheckHandler {
public void Check<T>(T someArg);
}
Hope that covers your scenario. You can not freely pass any CheckHandler around. Its Check method can then be called with an arbitrary type argument.
It is possible to have a single "thing" which can operate upon multiple parameter types, but the Delegate class is not suitable for that. Instead, you'll need to define an interface. As a simple example:
public interface IMunger<TConstraint>
{
void Munge<T>(ref T it) where T : TConstraint;
}
public class Cloner : IMunger<ICloneable>
{
public void Munge<T>(ref T it) where T : ICloneable
{
if (typeof(T).IsValueType) // See text
return;
it = (T)(it.Clone());
}
}
Even if the system had a pre-defined delegate type with a by-ref parameter (so that e.g. ActByRef<ICloneable> would have signature void Invoke(ref ICloneable p1)) such a delegate only be used on a variable of exact type ICloneable. By contrast, a single object of non-generic class type Cloner is able to provide a method suitable for use with any storage location type which implements ICloneable. Note also that if the method is passed a ref to a variable holding a reference to a boxed value-type instance, it will replace it with a reference to a copy of the instance, but if it is passed a ref to a value-type variable, it leave it as is (unless the value-type holds its state in a mutable class object to which it holds a reference--a very dodgy pattern--saying StructType foo = (StructType)(bar.Clone()); would be equivalent to just foo = bar; the structure type may want to implement ICloneable so to allow it to take part in a deep-cloning hierarchy, but that doesn't mean its Clone method needs to do anything.
Updated the example to support method as parameter which is just demonstating how to call generic delegate as parameter of other method.
class Program
{
public delegate T Transformer<T>(T arg) where T : IComparable;
public static void Transform<T>(T value, Transformer<T> method) where T: IComparable
{
Console.WriteLine(method(value));
}
static void Main(string[] args)
{
Transform(5, Square);
}
static int Square(int x)
{
return x * x;
}
}
I tried the following:
public class Test
{
public interface ISomeClass { }
public class ImplementsSomeClass : ISomeClass { }
public delegate void GenericDelegate<T>() where T : ISomeClass;
public void GenericMethod<T>()
{
// EDIT: returns typeof(ImplementsSomeClass)
var t = typeof(T);
}
public void CheckDelegate(GenericDelegate<ISomeClass> mechanism)
{
// EDIT: call without generic argument since it is already determined
mechanism();
}
public void test()
{
GenericDelegate<ISomeClass> someDelegate = GenericMethod<ImplementsSomeClass>;
CheckDelegate(someDelegate);
}
}
And I have no compilation errors. Is it a runtime problem or did I misunderstand your problem description?
Let's assume that I have two class.
public class A {...}
public class B : A {...}
What I want is to achieve is to override an extension function for both type.
public static void HelperExtension(this A a) {...}
public static void HelperExtension(this B b) {...}
I know that they are not virtual functions or behave like them. However I really wonder compiler behavior in this case.
Is there a way to call the function for type B without resolving its type? Or any auto-resolve suggestions?
This is not overriding - it is overloading, if anything.
It is fine - since the signatures are different, the compiler will not have any problem compiling it, even in the same namespace.
However, which extension method will be called depends on the exact type of the variable.
Now:
Is there a way to call the function for type B without resolving its type? Or any auto-resolve suggestions?
Without casting this is not possible. The extension is bound to the exact type that is being extended, so you need to have the exact type in order to call an extension on it.
This is why most of LINQ is defined on IEnumerable<T>.
As you said, there is no way of just making the extension virtual.
You could implement the entire virtual method pattern yourself through static methods but I have a strong feeling that's not going to be of any practical use to you, it's more of an interesting theoretical solution as the work involved would be prohibitive for something this simple.
If there are a fixed, finite number of possible sub classes you could have the first method have something like:
public static void HelperExtension(this A a)
{
B b = a as B;
if(b != null)
HelperExtension(b);
else
//the rest of the method.
}
You could use a Switch or even a Dictionary<Type, Action<A>> if you have a lot of subclasses, but it would be tedious, hard to maintain, and not support arbitrary inheritors not known at compile time.
Another option is to essentially leverage the compiler's functionality at compile time through the use of dynamic. I strongly advice avoiding it whenever possible, but in this particular case it would allow you to have a single public extension on A, a bunch of private static methods (with a different name) for each sub type, and then a single dispatch call:
public static void HelperExtension(this A a)
{
ExtenstionImplementation((dynamic)a);
}
private static void ExtenstionImplementation(A a){...}
private static void ExtenstionImplementation(B a){...}
private static void ExtenstionImplementation(C a){...}
I recently faced a similar problem. I have a third-party class library containing a hierarchy of class (let's say IBase, Base and Derived, where IBase is actually an interface).
public interface IBase {...}
public class Base : IBase {...}
public class Derived : Base {...}
Then, I have a class of mine which holds a reference ext to IBase. The concrete type of ext may be Base as well as Derived.
public class MyClass {
// other stuff
public IBase ext;
}
What I actually needed was a virtual method AddedMethod() defined within IBase and overridden in each descendant class, but that wasn't viable. So, one could be tempted to define a class containing a set of overloaded extension methods:
public static class MyExtensions
{
public static void AddedMethod(this IBase arg) {...}
public static void AddedMethod(this Base arg) {...}
public static void AddedMethod(this Derived arg) {...}
}
then, call ext.AddedMethod() on MyClass objects. This doesn't work: as extension methods are statically bound, the first method (i.e. AddedMethod(this IBase arg)) gets always called, regardless the actual type of ext.
The problem can be bypassed by defining a single extension method on IBase, then by using reflection to select the correct instance of a private static method whose argument type matches the actual type passed to the extension method:
public static class MyExtensions
{
// just one extension method
public static void AddedMethod(this IBase arg){
// get actual argument type
Type itsType = arg.GetType();
// select the proper inner method
MethodInfo mi = typeof(MyExtensions).GetMethod("innerAddedMethod",
BindingFlags.NonPublic | BindingFlags.Static,
null,
new Type[] { itsType },
null);
// invoke the selected method
if (mi != null) {
mi.Invoke(null, new object[] { arg });
}
}
private static void innerAddedMethod(Base arg) {
// code for Base type arg
}
private static void innerAddedMethod(Derived arg) {
// code for Derived type arg
}
Whether a new derived class Derived2 should be added to the IBase hierarchy, we'll have to simply add to MyExtensions class an overloaded innerAddedMethod() which takes Derived2 as its argument.
Consider two extension methods:
public static T MyExtension<T>(this T o) where T:class
public static T MyExtension<T>(this T o) where T:struct
And a class:
class MyClass() { ... }
Now call the extension method on a instance of the above class:
var o = new MyClass(...);
o.MyExtension(); //compiler error here..
o.MyExtension<MyClass>(); //tried this as well - still compiler error..
The compiler says that calling the method is an ambiguous call when I call it on a class. I would have thought that it could determine which extension method to call, as MyClass is a class, not a struct?
EDIT: I've now blogged about this in more detail.
My original (and I now believe incorrect) thought: generic constraints aren't taken into account during the overload resolution and type inference phases - they're only used to validate the result of the overload resolution.
EDIT: Okay, after a lot of going round on this, I think I'm there. Basically my first thought was almost correct.
Generic type constraints only act to remove methods from a candidate set in a very limited set of circumstances... in particular, only when the type of a parameter itself is generic; not just a type parameter, but a generic type which uses a generic type parameter. At that point, it's the constraints on the type parameters of the generic type which are validated, not the constraints on the type parameters of the generic method you're calling.
For example:
// Constraint won't be considered when building the candidate set
void Foo<T>(T value) where T : struct
// The constraint *we express* won't be considered when building the candidate
// set, but then constraint on Nullable<T> will
void Foo<T>(Nullable<T> value) where T : struct
So if you try to call Foo<object>(null) the above method won't be part of the candidate set, because Nullable<object> value fails to satisfy the constraints of Nullable<T>. If there are any other applicable methods, the call could still succeed.
Now in the case above, the constraints are exactly the same... but they needn't be. For example, consider:
class Factory<TItem> where TItem : new()
void Foo<T>(Factory<T> factory) where T : struct
If you try to call Foo<object>(null), the method will still be part of the candidate set - because when TItem is object, the constraint expressed in Factory<TItem> still holds, and that's what's checked when building up the candidate set. If this turns out to be the best method, it will then fail validation later, near the end of 7.6.5.1:
If the best method is a generic method, the type arguments (supplied or inferred) are checked against the constraints (ยง4.4.4) declared on the generic method. If any type argument does not satisfy the corresponding constraint(s) on the type parameter, a binding-time error occurs.
Eric's blog post contains more detail on this.
Eric Lippert explains better than I ever could, here.
I have come across this myself. My solution was
public void DoSomthing<T> (T theThing){
if (typeof (T).IsValueType)
DoSomthingWithStruct (theThing);
else
DoSomthingWithClass (theThing);
}
// edit - seems I just lived with boxing
public void DoSomthingWithStruct (object theThing)
public void DoSomthingWithClass(object theThing)
I found this "interesting" strange way to do that in .NET 4.5 using default parameter values :) Maybe is more useful for educational\speculative purposes than for real use but I would like to show it :
/// <summary>Special magic class that can be used to differentiate generic extension methods.</summary>
public class MagicValueType<TBase>
where TBase : struct
{
}
/// <summary>Special magic class that can be used to differentiate generic extension methods.</summary>
public class MagicRefType<TBase>
where TBase : class
{
}
struct MyClass1
{
}
class MyClass2
{
}
// Extensions
public static class Extensions
{
// Rainbows and pink unicorns happens here.
public static T Test<T>(this T t, MagicRefType<T> x = null)
where T : class
{
Console.Write("1:" + t.ToString() + " ");
return t;
}
// More magic, other pink unicorns and rainbows.
public static T Test<T>(this T t, MagicValueType<T> x = null)
where T : struct
{
Console.Write("2:" + t.ToString() + " ");
return t;
}
}
class Program
{
static void Main(string[] args)
{
MyClass1 t1 = new MyClass1();
MyClass2 t2 = new MyClass2();
MyClass1 t1result = t1.Test();
Console.WriteLine(t1result.ToString());
MyClass2 t2result = t2.Test();
Console.WriteLine(t2result.ToString());
Console.ReadLine();
}
}
Is there any way to do code such this:
class GenericClass<T>
{
void functionA()
{
T.A();
}
}
Or, how to call a function of type parameter (type is some my custom class).
Re:
T.A();
You can't call static methods of the type-parameter, if that is what you mean. You would do better to refactor that as an instance method of T, perhaps with a generic constraint (where T : SomeTypeOrInterface, with SomeTypeOrInterface defining A()). Another alternative is dynamic, which allows duck-typing of instance methods (via signature).
If you mean that the T is only known at runtime (as a Type), then you would need:
typeof(GenericClass<>).MakeGenericType(type).GetMethod(...).Invoke(...);
To call a method of a generic type object you have to instantiate it first.
public static void RunSnippet()
{
var c = new GenericClass<SomeType>();
}
public class GenericClass<T> where T : SomeType, new()
{
public GenericClass(){
(new T()).functionA();
}
}
public class SomeType
{
public void functionA()
{
//do something here
Console.WriteLine("I wrote this");
}
}
I think you are looking for generic type constraints:
class GenericClass<T> where T : MyBaseClass
{
void functionA<T>(T something)
{
something.A();
}
}
In terms of the code you posted - in order to call something on T, you will need to pass it as a parameter to functionA. The constraint you use will have to ensure that any T has an A method that can be used.
I understand from your code that you want to call a type parameter static method, and that's just impossible.
See here for more info : Calling a static method on a generic type parameter