Call a method of type parameter - c#

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

Related

Chose generic implementation if the type parameter is struct or class

I would like to implement my generic IQueue<T> interface in an efficient way by doing one implementation if T is struct and another if T is a class.
interface IQueue<T> { ... }
class StructQueue<T> : IQueue<T> where T : struct { ... }
class RefQueue<T> : IQueue<T> where T : class { ... }
The, I'd like to have a factory method which based on T's kind returns an instance of one or the other:
static IQueue<T> CreateQueue<T>() {
if (typeof(T).IsValueType) {
return new StructQueue<T>();
}
return new RefQueue<T>();
}
Of course, the compiler indicates that T should be non-nullable/nullable type argument respectively.
Is there a way to cast T into a struct kind (and into a class kind) to make the method compile? Is this kind of runtime dispatching even possible with C#?
You can use Reflection to do it like this:
static IQueue<T> CreateQueue<T>()
{
if (typeof(T).IsValueType)
{
return (IQueue<T>)Activator
.CreateInstance(typeof(StructQueue<>).MakeGenericType(typeof(T)));
}
return (IQueue<T>)Activator
.CreateInstance(typeof(RefQueue<>).MakeGenericType(typeof(T)));
}
This code uses the Activator.CreateInstance method to create queues at runtime. This method takes in the type of the object you want to create.
To create a Type that represents the generic class, this code uses the MakeGenericType method to create a closed generic Type object from the open generic types like StructQueue<>.
Yacoub Massad's answer is correct, but with a little modification, you don't need to run MakeGenericType for each call to CreateQueue.
The code below runs MakeGenericType once per type, since a separate static variable exists for each type of QueueFactory<T>, i.e QueueFactory<int>.queueType will get StructQueue<int>, while QueueFactory<string>.queueType will get RefQueue<int>
public class QueueFactory<T>
{
static Type queueType = typeof(T).IsValueType ?
typeof(StructQueue<>).MakeGenericType(typeof(T)) : typeof(RefQueue<>).MakeGenericType(typeof(T));
public static IQueue<T> CreateQueue()
{
return (IQueue<T>)Activator.CreateInstance(queueType);
}
}
In my semi-scientific test, it created 1 million instances in about a tenth of the time.

create exact instance from class name

i have two classes: Class1 and Class2
class Class1
{
public void method();
}
class Class2
{
public void method();
}
in another place I have the class type and I want to create an instance from it.
type is typeof(Class1) or typeof(Class2)
public void CreateInstance(Type type)
{
var instance = Activator.GetInstance(type);
instance.method(); //compile error: object doesn't contain method
}
a solution is I define an interface that my classes implement that interface.
interface IInterface
{
void method();
}
public void CreateInstance(Type type)
{
var instance = Activator.GetInstance(type);
((IInterface)instance).method();
}
because I can't access to class definition I can't do this. How can I do this?
This is what you need:
public void CreateInstance(Type type)
{
var instance = Activator.CreateInstance(type);
type.GetMethod("method").Invoke(instance, null);
}
Or, alternatively, use dynamic:
public void CreateInstance(Type type)
{
dynamic instance = Activator.CreateInstance(type);
instance.method();
}
NB: You had GetInstance instead of CreateInstance in your code, but I corrected it.
You can avoid reflection and performance issues entirely by using a generic method and dynamic:
public void CreateInstance<T>() where T:new()
{
dynamic instance=new T();
instance.method();
}
Which you can call simply by passing the type:
CreateInstance<Class1>();
CreateInstance<Class2>();
Type safety is lost either when using reflection or using dynamic. Checking for the existence of a method with reflection isn't any safer or less risky than having the runtime throw an exception - in both cases you have to handle an exceptional condition. What are you going to do when this exception occurs?
With dynamic, a missing method will raise a RuntimeBinderException specifying that a method is missing. If I changed the method call from method to method1 I'll get an exception saying:
'ConsoleApplication24.Class1' does not contain a definition for 'method1'
This way the code does not pay the reflection penalty for the normal cases. This is also safer - there is no way that the exception can be missed.
The only way that provides compile-type safety is to have the classes implement an interface and use it as a generic constraint, eg:
public static void CreateInstance<T>() where T : ISomething, new()
{
var instance = new T();
instance.method();
}
Best option would be to use interface for safety. But if you can't do that, you can invoke this method through reflection:
public class MyClass
{
public void Method()
{
Console.WriteLine("executed");
}
}
public class MyActivator
{
public static void CreateInstance(Type type)
{
var instance = Activator.CreateInstance(type);
var method = GetMethod("method");
method.Invoke(instance, null);
}
}
And then you call this by:
MyActivator.CreateInstance(typeof(MyClass));
Remember to add some checking if method is not null

Generic Method assigned to Delegate

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?

Pass in Generic Type to a method

Is this possible?
When a type gets passed in to a method, I want to instantiate the generic class myClass
public class myClass<T>
{
}
public void PassInType(Type myType)
{
myClass<myType> c=new myClass<myType>();
}
Update:
Okay since thats not possible, how do I do this
public myMethod(string myType)
{
myClass<myType> c=new myClass<myType>();
}
No; that's fundamentally impossible.
The whole point of generics is that they create compile-time types.
You're trying to create a type which is unknown at compile time.
You can do it using reflection, though. (typeof(MyClass<>).MakeGenericType(myType))

Generic question... Calling a static method from a generic class

I have a generic class:
public class MyList<LinkedItem> : List<LinkedItem> where LinkedItem : MyItem, new()
{
}
From that generic class, I would like to access a static function from the LinkedItem Class which is a descendant of MyItem class. (thus without creating an instance of the LinkedItem).
Is it possible?
Thank you,
Eric
Yes, it is possible, but you have to use reflection by obtaining a MethodInfo from typeof(T).GetMethod("Foo", BindingFlags.Public | BindingFlags.Static) and then calling Invoke on it.
It can be very useful, particularly if using the same technique on a ConstructorInfo rather than a MethodInfo, to create a generic factory that uses parameters in the constructor. It is though one to use sparingly. In particular, there is no way of guaranteeing at compile time that the type in question has a static method of the required signature, so type-safety is gone and such an error won't be caught until run-time.
It can be done through reflection. There's no straight forward way to do it since C# has no API constraints on static memebers.
I am not sure what is the scenario you're in, but in most cases this is not a recommended solution :)
public class MyList<LinkedItem> : List<LinkedItem>
where LinkedItem : MyItem, new()
{
public int CallStaticMethod()
{
// Getting a static method named "M" from runtime type of LinkedItem
var methodInfo = typeof(LinkedItem)
.GetMethod("M", BindingFlags.Static | BindingFlags.Public);
// Invoking the static method, if the actual method will expect arguments
// they'll be passed in the array instead of empty array
return (int) methodInfo.Invoke(null, new object[0]);
}
}
public class MyItem
{
}
class MyItemImpl : MyItem
{
public MyItemImpl()
{
}
public static int M()
{
return 100;
}
}
So, for example the next code will print 100:
public void Test()
{
Console.WriteLine(new MyList<MyItemImpl>().CallStaticMethod());
}
No this is not possible directly from the type parameter because you cannot invoke static methods on generic type parameters (C# Lang Spec section 4.5).
A type parameter cannot be used in a member access (§7.5.4) or type name (§3.8) to identify a static member or a nested type.
Yes this is possible to achieve via reflection tricks as other people noted. But generally speaking using reflection to solve a simple method invocation scenario is an indication of bad design.
A much better design would be to pass a factory / delegate around which encapsulates the static method in a type safe manner.
class MyItem : MyItem {
static void TheFunction() { ... }
}
public class MyList<LinkedItem> : List<LinkedItem> where LinkedItem : MyItem, new()
{
public MyList(Action theStaticFunction) {
...
}
}
new MyList<MyItem>(MyItem.TheFunction);
This isn't possible. There's no way to declare a constraint on the LinkedItem parameter that says that it must contain the static method in question.
Possibly the closest you'll get is:
public class ILinkedItemFactory<T>
{
void YourMethodGoesHere();
}
public class MyList<LinkedItem, Factory> : List<LinkedItem>
where Factory : ILinkedItemFactory<LinkedItem>
where LinkedItem : MyItem, new()
{
public MyList(Factory factory)
{
factory.YourMethodGoesHere();
}
}
This is, by default, not possible. However, if you know the name of the method you want to invoke, and you are positive that every LinkedItem type will contain this method, you can use reflection to reach your goal. Note: there's often a better way than resolving to reflection for general programming tasks.
The following will always output true for DoSomething. It invokes a static member that's always available (I removed your generic type constraint, as that's not important with static methods).
public class MyList<LinkedItem> : List<LinkedItem>
{
public bool DoSomething()
{
Type t = typeof(LinkedItem);
object o = new Object();
var result = t.InvokeMember("ReferenceEquals",
BindingFlags.InvokeMethod |
BindingFlags.Public |
BindingFlags.Static,
null,
null, new[] { o, o });
return (result as bool?).Value;
}
}
// call it like this:
MyList<string> ml = new MyList<string>();
bool value = ml.DoSomething(); // true
PS: meanwhile, while I typed this, others seem to suggest the same approach ;-)
This is completely possible though not directly in the way you are stating without maybe reflection. You would want to implement a non-static access method in the baseclass and have it overridden in every specific inheriting class.
public class MyItem
{
public static void DoSomeStaticStuff() { //DoSomeStaticStuff for MyItem }
public virtual void AccessSomeStaticStuff() { MyItem.DoSomeStaticStuff(); }
}
public class SomeItem : MyItem
{
public static void DoSomeStaticStuff() { //DoSomeStaticStuff for SomeItem }
public override void AccessSomeStaticStuff() { SomeItem.DoSomeStaticStuff(); }
}
Then in your class which has the constraint where T : MyItem you would just call T.AccessSomeStaticStuff();

Categories