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?
Related
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.
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.
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))
I have a lot of unit tests that pretty much tests the same behavior. However, data type changes.
I am trying to create a generic method that can take any data type. I tried making my input parameter var but that's not allowed. Also, looked into c# generics but that usually deals with a list.
You could make the parameter an object:
public void DoSomething(object arg)
{
//...
Or you could do what I prefer and make a generic method:
public void DoSomething<T>(T arg)
{
//...
The generic approach has two major advantages, and I'll give examples of why they're useful:
Even though you don't explicitly specify the type of arg, you still have access to it.
You can add constraints on the types you want to allow.
Conversely, the object approach has some important disadvantages:
Since you're treating arg as an object, you'll only be able to do things you could do with any object.
If you pass a value type as an object parameter, the variable will be boxed, which means a performance hit. It's not a huge hit, but if you call DoSomething several thousand times in a row, you might start feeling it.
Generics and Type Constraints
Adding a type constraint to a generic method allows you to restrict the method so that it only accepts certain types. Why is that useful? Because even though you don't know—or care—what specific type you're working with, you now know something about it, and you can use that information.
Consider the following setup:
public interface IAnimal
{
void Move();
}
public class Duck : IAnimal
{
public void Move()
{
Console.WriteLine("Flying");
}
}
public class Fish : IAnimal
{
public void Move()
{
Console.WriteLine("Swimming");
}
}
public class Ant : IAnimal
{
public void Move()
{
Console.WriteLine("Walking");
}
}
Since we have an IAnimal interface, we can write generic methods targeting any implementation of IAnimal:
public class Program
{
static void DoMove<T>(T animal) where T : IAnimal
{
animal.Move();
}
public static void Main(string[] args)
{
Duck duck = new Duck();
Fish fish = new Fish();
Ant ant = new Ant();
DoMove<Duck>(duck);
DoMove<Fish>(fish);
DoMove<Ant>(ant);
}
}
Run it: http://rextester.com/GOF1761
When we write the DoMove method, we don't care whether its parameter animal is a Duck, a Fish, an Ant, or anything else. All we care about is calling animal.Move(). Since we used the where T : IAnimal constraint, the compiler knows everything we need it to know:
The variable animal is of type T.
Whatever T is, it implements IAnimal.
Anything that implements IAnimal has a Move() method.
Therefore, we can safely call animal.Move().
(By the way, yes, we could just write DoMove as static void DoMove(IAnimal animal), but that's another discussion.)
Type Inference (and some of its implications)
Fine, but let's take it a step further. In many cases, you can call generic methods without having to specify their type parameters. This is called type inference, and aside from saving you some typing, it can be useful when doing the same operation on objects of different types.
public static void Main(string[] args)
{
IAnimal[] animals = new IAnimal[]
{
new Duck(),
new Fish(),
new Ant()
};
foreach (IAnimal animal in animals)
{
DoMove(animal);
}
}
Run it: http://rextester.com/OVKIA12317
You only have to write the DoMove<T> method once, and you can call it on any type of IAnimal without having to give a more specific type. The appropriate version of Move will be called each time, because DoMove<T> is able to infer which type to use for T. When you call DoMove(duck), .NET understands that you really mean DoMove<Duck>(duck), which then calls the Move method on the Duck class.
You can take in object as a parameter type. Even better, perhaps, would be to use generics:
void MyMethod<T>(T parm) { ... }
This way the parameter is actually of the type the user passed in -- it isn't boxed like with object and value types.
void MyTestMethod<T>(T t) { }
gets you a generic test method, but I can't imagine any way that could be useful. What do you need to test? How do you know type T has those methods? T can be any type in the above method. The only methods you can call from t in the above example are the common methods of object.
What you really need to do is identify a common behaviour against one or more types which you want to test, and define the syntactical contract of that behaviour through an interface. You can then constrain your generic test method to only accept types which implement that interface.
interface IMyInterface
{
void DoSomething();
}
void MyTestMethod<T>(T t) where T : IMyInterface
{
t.DoSomething();
}
public void YourMethod<T>(T parameter)
{
}
Make your parameter type "object" and your method will accept every type as input. Then you can detect its type using GetType(), and even use tools like int.Parse, ToString(), and type casting to convert your input to a specific type and then work with it.
static void whatsmytype(object place) // Will accept any type
{
Type t = place.GetType(); // detects type of "place" object
if (t.Equals(typeof(string)))
Console.WriteLine("Type is string.");
else if (t.Equals(typeof(int)))
Console.WriteLine("Type is int.");
else
Console.WriteLine("Type is unknown.");
}
Edit: If readability is not really an issue, you could replace the method declaration line with code below, to get a minor speed improvement:
static void whatsmytype<T>(T place)
try to use dynamic keyword, this will work provided that all of your different types have the same methods that are used by your unit tests, otherwise you will get a run-time exception
public class BinarySearchTree<T>
where T : IComparable<T>
{
public static BinarySearchTree<char> InitializeSampleCharacterBST()
{
var bst = new BinarySearchTree<char>();
bst.Insert('F');
bst.Insert('B');
bst.Insert('A');
bst.Insert('D');
bst.Insert('C');
bst.Insert('G');
bst.Insert('I');
bst.Insert('H');
return bst;
}
class Program
{
static void Main(string[] args)
{
var bst = BinarySearchTree.InitializeSampleCharacterBST();
}
}
Why is this illegal? It's expecting me to provide a type parameter to the method call for the class which makes no sense. A generic class or method has no use for a type parameter in a static context.
It wants me to write the call like this:
var bst = BinarySearchTree<foo>.InitializeSampleCharacterBST();
Where foo can be any type I want regardless of the fact that the static method call returns a specifically typed generic object.
the class BinarySearchTree and BinarySeachTree<Foo> are completely separate; the language allows generic type overloading. Perhaps declare this method on a non-generic twin class:
public static class BinarySearchTree {
public static BinarySearchTree<char> InitializeSampleCharacterBST() {...}
}
public class BinarySearchTree<T> {...} // rest of the code
Otherwise... what T would it use? And what if the static method talked to static fields? Let alone which T to use, each T gets different static fields (i.e. SomeType<Foo> has separate fields to SomeType<Bar>).
As Marc said, it's sometimes useful to overload the type to have a non-generic class - and it would be in this case.
As for why it's necessary, suppose that the static method were actually implemented as:
public static BinarySearchTree<char> InitializeSampleCharacterBST()
{
Console.WriteLine(typeof(T));
return null;
}
That would be perfectly valid code - it's in a generic type, so it should have access to the type parameter... but you're trying to call the method without providing a generic type parameter, so it couldn't possibly work. In your case you happen to not use T anywhere within the method, but that's a coincidence. It's a bit like having an instance method which doesn't use this: you're not using the instance, but you still can't call it as if it were a static method.
As well as having separate static classes, another design technique which can be useful is to split your type into non-generic and generic pieces. That way, in cases where it can be awkward to work out which exact type you have, you don't actually need to know it in order to call some of the members. For example, a collection interface hierarchy might have:
public interface ISomeCollection
{
int Count { get; }
void Clear();
}
public interface ISomeCollection<T> : ISomeCollection
{
void Add(T item);
}
I've used this technique myself for my Protocol Buffers port to C#, and it's proved very useful (if somewhat complicated).
You're forgetting that type parameters don't only appear in the parameter/return type of a method. They can also appear in the implementation:
public static BinarySearchTree<char> InitializeSampleCharacterBST()
{
var forSomeReason = new T();
By placing your method inside a static class with a type parameter, you are saying that the implementation of the method may (now or in some future revision) depend upon that type parameter.
If this isn't the case, you've put the method in the wrong place.
Because the type itself is Generic, you have to provide a type argument, even if the static method you are interested in does not make use of that type argument. Its just the nature of generics in C#...they don't exist in a non-generic form at any time. If they did, that would cause conflicts with a non-generic version of the same type.