Static generic delegate field in C# - c#

Using generic types is nice and easy, but since I tried to implement my own generic types, I came to a problem which I couldn't solve by myself yet. I want to have a static field for a delegate. This is how it works for me when using non-generic types:
delegate Type Type_Delegate(Type type);
static Type_Delegate TypeMethod = new Type_Delegate(TypeMethodName);
// Now the TypeMethod can be called like this from somewhere in the Code:
ClassName.TypeMethod(typeof(string));
But when using any generic type:
delegate T Type_Delegate<T>(T type);
// This static field syntax isn't allowed:
static Type_Delegate<T> TypeMethod = new Type_Delegate<T>(TypeMethodName);
// It would be a dream to be able to use it like this now:
ClassName.TypeMethod<string>("Hello world!");
T is unknown type/namespace.
When I experiment with the syntax:
// This static field syntax isn't allowed, too:
static Type_Delegate TypeMethod = new Type_Delegate(TypeMethodName);
Type arguments are missing for usage.
I tried several ideas about the possible syntax, but not succeed...
How do I need to change the static field syntax to work as assumed, so the code is able to set a generic delegate method as value, without having to specify a type at that time?
Edit: I also tried to wrap the delegate and field with a generic static class, but there I still have the same syntax issues, when I want to set the field value without specifying the type.
Edit 2: Maybe the following example workaround apporach will clarify my thoughts more, since I think most commenters didn't understand my goal (maybe it's my bad English, too):
using System;
using System.Linq;
using System.Reflection;
namespace Testing
{
public static class GenericTest
{
public interface IGenericClass<T>
{
T Method(T parameter);
}
public class GenericClass<T> : IGenericClass<T>
{
public T Method(T parameter)
{
// Just a stupid example, don't think about that...
return parameter;
}
}
/// <summary>
/// The value must be any type that implements the IGenericClass<T> interface
/// </summary>
public static Type GenericField = typeof(GenericClass<>);
/// <summary>
/// Call the method of an instance of the type that was set to GenericField
/// </summary>
/// <param name="T">The type to use for creating an instance of the generic class</param>
/// <param name="parameter">The parameter for calling the method of the generic class</param>
/// <returns>Any value of type "T"</returns>
public static dynamic GenericMethod(Type T, object parameter)
{
var genericType = GenericField.MakeGenericType(new Type[] { T });
MethodInfo method = genericType.GetMethod("Method");
if (method == null) throw new InvalidCastException("GenericField isn't a IGenericClass<T> type");
return method.Invoke(Activator.CreateInstance(genericType), new object[] { parameter });
}
}
}
Now I can do something like this somewhere else in the code:
MessageBox.Show(Testing.GenericTest.GenericMethod(typeof(string), "Hello world!"));
In this example solution I need to work with classes and an interface, require reflections, it's a whole bunch of code required to get the same functionality for a generic (class-)method, as I can get with only two lines of code when working with non-generic methods (using delegates). What an overhead, what a hack - I try to avoid doing such nasty things in productive code. But if there are no better 2 lines of Code that do the same, this time I will have to fight my ego...

It is possible, by wrapping it in a generic class definition and using the class type parameter.
static class C<T>
{
public static DelegateTypePrototype<T> DelegateType;
}
This way the type only has to be resolved once you "request" an instance of the class. At least that's my intuitive understanding coming from C++ templates background.

Related

is it necessary to use MakeGenericType method?

I saw code like this:
internal sealed class MyDictionary<TKey, TValue> { }
public static class Program {
public static void Main() {
// Get a reference to the generic type's type object
Type openType = typeof(MyDictionary<,>);
// Close the generic type by using TKey=String, TValue=Int32
Type closedType = openType.MakeGenericType(typeof(string), typeof(int));
// Construct an instance of the closed type
Object o = Activator.CreateInstance(closedType);
Console.WriteLine(o.GetType());
}
}
But why we need to use the MakeGenericType method, why not just do:
...
Type concreteType= typeof(MyDictionary<string, int>);
Object o = Activator.CreateInstance(concreteType);
Console.WriteLine(o.GetType());
the results are the same.
It looks like MakeGenericType method add extra unnecessity, so does MakeGenericType provide useful features that I overlook?
MakeGenericType is for when you don't know the type at compile time. Therefore you are correct - you wouldn't really use the code you saw, as the types were known at compile time, so you may as well write new MyDictionary<string, int>().
However, the code could rewritten like this:
internal sealed class MyDictionary<TKey, TValue> { }
public static class Factory {
public static MyDictionary<TKey, TValue> Create<TKey, TValue>() {
// Get a reference to the generic type's type object
Type openType = typeof(MyDictionary<,>);
// Close the generic type by using type constraints
Type closedType = openType.MakeGenericType(typeof(TKey), typeof(TValue));
// Construct an instance of the closed type
Object o = Activator.CreateInstance(closedType);
return (MyDictionary<TKey, TValue>)o;
}
}
These two would effectively create the same object:
var dictionary0 = new MyDictionary<string, int>();
var dictionary1 = Factory.Create<string, int>();
Console.WriteLine(dictionary0.GetType() == dictionary1.GetType());
// true
Even here it's not that useful because the return type requires generic constraints. Where I use it is for situations that require an interface or abstract return type, but you need to create a generic implementation, for example:
internal sealed class MyDictionary<TKey, TValue> : ISomeFeature { }
public static class Factory {
public static ISomeFeature Create(Type key, Type value) {
// Get a reference to the generic type's type object
Type openType = typeof(MyDictionary<,>);
// Close the generic type by using arguments
Type closedType = openType.MakeGenericType(key, value);
// Construct an instance of the closed type
Object o = Activator.CreateInstance(closedType);
return (ISomeFeature)o;
}
}
Now suddenly it becomes a whole lot more useful. Because it relies on Type objects instead of generic constraints, you can pass it types dynamically - i.e. at run time.
Short answer: NO! it is not necessary to use makeGenericType, but sometimes it's a necessity
Generics are best used when you know the types at compile time. In fact there is a good argument that if you don't know the types at compile time, you probably shouldnt be using generics!
That said, there are often times when you need to use a generic implementation (perhaps a 3rd party library) and you only know the types at runtime... that is where Reflection, and specifically MakeGenericType comes in.
You code was no doubt an example of how to do this, because actually that code is only doing
var dict = new MyDictionary<string,int>();
Console.WriteLine(dict.GetType());
Assuming the types were known at compile time.

Cast dynamic to type through external static extension call stays dynamic

I have a strange behaviour.
I use the following method to cast any object to any given type.
using System.Dynamic;
...
/// <summary>
/// Casts any object to passed type.
/// </summary>
/// <typeparam name="T">Wished type</typeparam>
/// <param name="obj">The object you want to be casted.</param>
public static T ToType<T>(this object obj) => (T)obj;
For example (object to dynamic):
AnyLabel.Tag = new ExpandoObject();
AnyLabel.Tag.ToType<dynamic>().Item2 = new Form(); // works
Now following situation (dynamic to typed object):
// var is NOT from type form, why?:
var form = ToType<Form>(AnyLabel.Tag.ToType<dynamic>().Item2);
// the other way works like desired:
var form2 = ((Form)AnyLabel.Tag.ToType<dynamic>().Item2);
I can not access any form properties/methods using the casting extension à la:
ToType<Form>(AnyLabel.Tag.ToType<dynamic>().Item2).Show();
My question is, why is the first var not from type form and denies me the last code part to execute?
The method ToType<T>() could have overloaded versions. If no dynamics are involved, the compiler resolves the right overload at compile time. If; however, dynamics are involved, the binding happens at runtime, i.e., the right overload is determined at runtime using the runtime type of the arguments. Also, these overloads could have different return types. Since now, this return type is not known at compile time, the C# compiler decides to choose dynamic as return type of your function.
Now, you could reason, that you don't have an overloaded version and that Form could safely be assumed. But what happens, if you add overloads later? Should this suddenly change the return type of an expression that did not change? Adding an overload, would introduce a breaking change to existing code that cannot be detected at compile time.
Which return type to choose at compile time, if overload is determined by runtime argument type?
public static T ToType<T>(this object obj) => (T)obj;
public static int ToType<T>(this int i) => i; // Makes no sense, but valid code.
public static dynamic ToType<T>(this dynamic d) => d; // Valid as well.

Why are type parameters not allowed in constructors?

There are type parameters for methods. Why there are no type parameters for constructors?
Example
I think there are several (not many) examples where it would be usefull. My current problem was following:
internal class ClassA
{
private readonly Delegate _delegate;
public ClassA<T>(Func<T> func)
{
_delegate = func;
}
}
A Delegate is enough for my class. But to pass it as method group I need to define the parameter as a Func<T>.
After reading the C# specification it actually does make sense, but it can be confusing.
Each class has an associated instance type, and for a generic class declaration the instance type is formed by creating a constructed type from the type declaration, with each of the supplied type arguments being the corresponding type parameter.
class C<T>
{
}
C<T> is a constructed type, and an instance type will be created by the process of constructing the type using the type parameters.
C<String> c = new C<String>();
The compiler took the constructed type C<T>, and using the supplied type parameters an instance type of C<String> was created. Generics is only a compile time construct, everything is executed in the terms of closed constructed types at runtime.
Now let's take your question and put it to the test here.
class C
{
public C<T>()
{
}
}
This isn't possible, because you are trying to construct a type that doesn't exist.
C c = new C<String>();
What is the implicit or explicit conversion between C and C<String>? There is none. It doesn't even make sense.
Because C is a non-generic type in this example, the instance type is the class declaration itself. So how do you expect C<String> to construct C?
The proper declaration for what you want to do is this.
internal class Class<T>
{
private readonly Delegate _delegate;
public Class(Func<T> function)
{
_delegate = function;
}
}
Here because we have a constructed type Class<T>, the proper instance type can be created by the compiler.
Func<String> function = new Func<String>(() => { return String.Empty; });
Class<String> c = new Class<String>(function);
If you tried to do it the way you want in your question.
Func<String> function = new Func<String>(() => { return String.Empty; });
Class c = new Class<String>(function);
The constructed type would be Class<String>, which is not the same as type C, and there is no implicit or explicit conversion from either one. If this was allowed by the compiler, C would be in some unknown and unusable state.
What you do need to know about constructed types, is this.
class C<T>
{
public C<T>()
{
}
}
While you cannot explicitly declare a generic constructor, it is valid but only as a closed type constructor at runtime.
C<String> c = new C<String>();
At compile time, the following constructor is created.
public C<String>()
{
}
Which is why this is valid:
C<String> c = new C<String>(); // We just used the closed type constructor
If what you wanted was allowed, something like this could happen.
class C<T>
{
public C<U>()
{
}
}
// ???
C<String> c = new C<Int32>();
You can see the problems now that would arise if the construct was allowed. Hopefully this sheds some insight, the specification is rather long and there are many many many sections that cover generics, type parameters, constructed types, closed and open types, bound and unbound.
It can get very confusing, but its a good thing that this isn't allowed by the compiler rules.
They simply didn't include the feature, probably on the assumption that it wouldn't be very useful.
If you need it for the constructor, you probably need it for the whole type. But in the cases you don't, you can probably use Object anyway.
And if you can't... yeah, I don't think there's much of a way around it, sorry. :\ You can use reflection but of course that'd be ridiculously slow... or you could play tricks with generating methods dynamically, which might be worth it depending on your use case but which might also be slow (it adds at least 1 extra indirect call).
Because a constructor is part of a class and so the type parameters probably belong on the whole type.
If you can choose a different type parameter to use when constructing an instance of a generic class then you are really constructing a different type of class. I know it's not the same as templated classes in C++ but the concept is similar.
To solve your particular issue you could use a 'templated' factory method.
You can pass in a delegate instead of a strongly typed Func<T>. You will not be able to know the type at compile time, but you wouldn't have that when you pass in the Func<T> either. When you want that you'd have to make the whole class generic.
class Program {
static void Main(string[] args) {
Func<int> i = () => 10;
var a1 = new ClassA(i);
Func<string> s = () => "Hi there";
var a2 = new ClassA(s);
}
}
internal class ClassA {
private readonly Delegate _delegate;
public ClassA(Delegate func) { // just pass in a delegate instead of Func<T>
_delegate = func;
}
}
Because you can achive that by declaring your class as generic
internal class ClassA<T>
{
private readonly Delegate _delegate;
public ClassA(Func<T> func)
{
_delegate = func;
}
}
then you will have implicitly a generic construct

Extension Methods and generics - How should I be doing this?

I'm in the middle of overhauling some code and I hit a bit of a snag.
This is the method which I currently have, it needs reworking to support some structure changes:
/// <summary>
/// Recreates a dashboard control based off of its settings.
/// </summary>
/// <typeparam name="T"> The type of control to be recreated. </typeparam>
/// <param name="settings"> The known settings needed to recreate the control.</param>
/// <returns> The recreated control. </returns>
public static T Recreate<T>(ISetting<T> settings) where T : new()
{
T _control = new T();
settings.SetSettings(_control);
Logger.DebugFormat("Recreated control {0}", (_control as Control).ID);
return _control;
}
ISetting is being removed completely in favor of an extension method known to _control.
So, I have now:
public static class RadControlExtensions
{
public static RadDockZoneSetting GetSettings(this RadDockZone dockZone)
{
RadDockZoneSetting radDockZoneSetting = new RadDockZoneSetting(dockZone.UniqueName, dockZone.ID, dockZone.Skin, dockZone.MinHeight,
dockZone.HighlightedCssClass, dockZone.BorderWidth, dockZone.Parent.ID);
return radDockZoneSetting;
}
public static RadTabSetting GetSettings(this RadTab tab, int index)
{
RadTabSetting radTabSetting = new RadTabSetting(tab.Text, tab.Value, index);
return radTabSetting;
}
//Continued
}
The control that is being recreated is guaranteed to have this extension method (would be nice to enforce this, though.)
I'm now at:
public static T Recreate<T>() where T : new()
{
T _control = new T();
//Not right -- you can't cast a control to an extension method, obviously, but
//this captures the essence of what I would like to accomplish.
(_control as RadControlExtension).SetSettings();
Logger.DebugFormat("Recreated control {0}", (_control as Control).ID);
return _control;
}
What should I be looking into to support this, if possible?
If you know that every _control that gets passed will be a RadDockZone (or derived from RadDockZone) just do this:
T _control = new T();
(RadDockZone)_control.SetSettings();
Logger.DebugFormat("Recreated control ... //rest of code here
If it's not always going to be a RadDockZone, you'll need to do some type checking to get the right type to call the extension method. I'm presuming, there, that you have a .SetSettings() extension method on all the possible Types that could be passed to your Recreate method.
You need to cast your T to something that is supported by your extension method.
(_control as RadDockZone).GetSettings
Extension methods operate on a type they are not a type in the traditional sense. The 'SomeFn(string this)' makes your extension work on things that are strings which would be strings and anything derived from them.
If I understand correctly what you are trying to do, just put a constraint on T:
public static T Recreate<T>() where T : RadControl, new() {
// etc.
}
You might have to use double dispatch and define
public static RadControl GetSettings(this RadControl control) {
}
which will invoke the appropriate GetSettings method.
No, Jason's answer is the cleaner way to go. The accepted solution killed the type safety and made use of generics pointless. You could switch to generic-less design (having a RadControlFactory) and had the job done.

Partial generic type inference possible in C#?

I am working on rewriting my fluent interface for my IoC class library, and when I refactored some code in order to share some common functionality through a base class, I hit upon a snag.
Note: This is something I want to do, not something I have to do. If I have to make do with a different syntax, I will, but if anyone has an idea on how to make my code compile the way I want it, it would be most welcome.
I want some extension methods to be available for a specific base-class, and these methods should be generic, with one generic type, related to an argument to the method, but the methods should also return a specific type related to the particular descendant they're invoked upon.
Better with a code example than the above description methinks.
Here's a simple and complete example of what doesn't work:
using System;
namespace ConsoleApplication16
{
public class ParameterizedRegistrationBase { }
public class ConcreteTypeRegistration : ParameterizedRegistrationBase
{
public void SomethingConcrete() { }
}
public class DelegateRegistration : ParameterizedRegistrationBase
{
public void SomethingDelegated() { }
}
public static class Extensions
{
public static ParameterizedRegistrationBase Parameter<T>(
this ParameterizedRegistrationBase p, string name, T value)
{
return p;
}
}
class Program
{
static void Main(string[] args)
{
ConcreteTypeRegistration ct = new ConcreteTypeRegistration();
ct
.Parameter<int>("age", 20)
.SomethingConcrete(); // <-- this is not available
DelegateRegistration del = new DelegateRegistration();
del
.Parameter<int>("age", 20)
.SomethingDelegated(); // <-- neither is this
}
}
}
If you compile this, you'll get:
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingConcrete' and no extension method 'SomethingConcrete'...
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingDelegated' and no extension method 'SomethingDelegated'...
What I want is for the extension method (Parameter<T>) to be able to be invoked on both ConcreteTypeRegistration and DelegateRegistration, and in both cases the return type should match the type the extension was invoked on.
The problem is as follows:
I would like to write:
ct.Parameter<string>("name", "Lasse")
^------^
notice only one generic argument
but also that Parameter<T> returns an object of the same type it was invoked on, which means:
ct.Parameter<string>("name", "Lasse").SomethingConcrete();
^ ^-------+-------^
| |
+---------------------------------------------+
.SomethingConcrete comes from the object in "ct"
which in this case is of type ConcreteTypeRegistration
Is there any way I can trick the compiler into making this leap for me?
If I add two generic type arguments to the Parameter method, type inference forces me to either provide both, or none, which means this:
public static TReg Parameter<TReg, T>(
this TReg p, string name, T value)
where TReg : ParameterizedRegistrationBase
gives me this:
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Which is just as bad.
I can easily restructure the classes, or even make the methods non-extension-methods by introducing them into the hierarchy, but my question is if I can avoid having to duplicate the methods for the two descendants, and in some way declare them only once, for the base class.
Let me rephrase that. Is there a way to change the classes in the first code example above, so that the syntax in the Main-method can be kept, without duplicating the methods in question?
The code will have to be compatible with both C# 3.0 and 4.0.
Edit: The reason I'd rather not leave both generic type arguments to inference is that for some services, I want to specify a parameter value for a constructor parameter that is of one type, but pass in a value that is a descendant. For the moment, matching of specified argument values and the correct constructor to call is done using both the name and the type of the argument.
Let me give an example:
ServiceContainerBuilder.Register<ISomeService>(r => r
.From(f => f.ConcreteType<FileService>(ct => ct
.Parameter<Stream>("source", new FileStream(...)))));
^--+---^ ^---+----^
| |
| +- has to be a descendant of Stream
|
+- has to match constructor of FileService
If I leave both to type inference, the parameter type will be FileStream, not Stream.
I wanted to create an extension method that could enumerate over a list of things, and return a list of those things that were of a certain type. It would look like this:
listOfFruits.ThatAre<Banana>().Where(banana => banana.Peel != Color.Black) ...
Sadly, this is not possible. The proposed signature for this extension method would have looked like:
public static IEnumerable<TResult> ThatAre<TSource, TResult>
(this IEnumerable<TSource> source) where TResult : TSource
... and the call to ThatAre<> fails because both type arguments need to be specified, even though TSource may be inferred from the usage.
Following the advice in other answers, I created two functions: one which captures the source, and another which allows callers to express the result:
public static ThatAreWrapper<TSource> That<TSource>
(this IEnumerable<TSource> source)
{
return new ThatAreWrapper<TSource>(source);
}
public class ThatAreWrapper<TSource>
{
private readonly IEnumerable<TSource> SourceCollection;
public ThatAreWrapper(IEnumerable<TSource> source)
{
SourceCollection = source;
}
public IEnumerable<TResult> Are<TResult>() where TResult : TSource
{
foreach (var sourceItem in SourceCollection)
if (sourceItem is TResult) yield return (TResult)sourceItem;
}
}
}
This results in the following calling code:
listOfFruits.That().Are<Banana>().Where(banana => banana.Peel != Color.Black) ...
... which isn't bad.
Notice that because of the generic type constraints, the following code:
listOfFruits.That().Are<Truck>().Where(truck => truck.Horn.IsBroken) ...
will fail to compile at the Are() step, since Trucks are not Fruits. This beats the provided .OfType<> function:
listOfFruits.OfType<Truck>().Where(truck => truck.Horn.IsBroken) ...
This compiles, but always yields zero results and indeed doesn't make any sense to try. It's much nicer to let the compiler help you spot these things.
If you have only two specific types of registration (which seems to be the case in your question), you could simply implement two extension methods:
public static DelegateRegistration Parameter<T>(
this DelegateRegistration p, string name, T value);
public static ConcreteTypeRegistration Parameter<T>(
this ConcreteTypeRegistration p, string name, T value);
Then you wouldn't need to specify the type argument, so the type inference would work in the example you mentioned. Note that you can implement both of the extension methods just by delegation to a single generic extension method with two type parameters (the one in your question).
In general, C# doesn't support anything like o.Foo<int, ?>(..) to infer only the second type parameter (it would be nice feature - F# has it and it's quite useful :-)). You could probably implement a workaround that would allow you to write this (basically, by separating the call into two method calls, to get two places where the type inferrence can be applied):
FooTrick<int>().Apply(); // where Apply is a generic method
Here is a pseudo-code to demonstrate the structure:
// in the original object
FooImmediateWrapper<T> FooTrick<T>() {
return new FooImmediateWrapper<T> { InvokeOn = this; }
}
// in the FooImmediateWrapper<T> class
(...) Apply<R>(arguments) {
this.InvokeOn.Foo<T, R>(arguments);
}
Why don't you specify zero type parameters? Both can be inferred in your sample. If this is not an acceptable solution for you, I'm frequently encountering this problem too and there's no easy way to solve the problem "infer only one type parameter". So I'll go with the duplicate methods.
What about the following:
Use the definition you provide:
public static TReg Parameter<TReg, T>(
this TReg p, string name, T value)
where TReg : ParameterizedRegistrationBase
Then cast the parameter so the inference engine gets the right type:
ServiceContainerBuilder.Register<ISomeService>(r => r
.From(f => f.ConcreteType<FileService>(ct => ct
.Parameter("source", (Stream)new FileStream(...)))));
I think you need to split the two type parameters between two different expressions; make the explicit one be part of the type of a parameter to the extension method, so inference can then pick it up.
Suppose you declared a wrapper class:
public class TypedValue<TValue>
{
public TypedValue(TValue value)
{
Value = value;
}
public TValue Value { get; private set; }
}
Then your extension method as:
public static class Extensions
{
public static TReg Parameter<TValue, TReg>(
this TReg p, string name, TypedValue<TValue> value)
where TReg : ParameterizedRegistrationBase
{
// can get at value.Value
return p;
}
}
Plus a simpler overload (the above could in fact call this one):
public static class Extensions
{
public static TReg Parameter<TValue, TReg>(
this TReg p, string name, TValue value)
where TReg : ParameterizedRegistrationBase
{
return p;
}
}
Now in the simple case where you are happy to infer the parameter value type:
ct.Parameter("name", "Lasse")
But in the case where you need to explicitly state the type, you can do so:
ct.Parameter("list", new TypedValue<IEnumerable<int>>(new List<int>()))
Looks ugly, but hopefully rarer than the simple fully-inferred kind.
Note that you could just have the no-wrapper overload and write:
ct.Parameter("list", (IEnumerable<int>)(new List<int>()))
But that of course has the disadvantage of failing at runtime if you get something wrong. Unfortunately away from my C# compiler right now, so apologies if this is way off.
I would used the solution:
public class JsonDictionary
{
public static readonly Key<int> Foo = new Key<int> { Name = "FOO" };
public static readonly Key<string> Bar = new Key<string> { Name = "BAR" };
IDictionary<string, object> _data;
public JsonDictionary()
{
_data = new Dictionary<string, object>();
}
public void Set<T>(Key<T> key, T obj)
{
_data[key.Name] = obj;
}
public T Get<T>(Key<T> key)
{
return (T)_data[key.Name];
}
public class Key<T>
{
public string Name { get; init; }
}
}
See:
C#: Exposing type safe API over heterogeneous dictionary

Categories