I have a generic function as follows:
public static T Function<T>(Argument arg)
{
//DO FUNCTION STUFF
}
I want to call this function using a Type I get from FieldInfo.FieldType like so:
Function<someFieldInfo.FieldType>(arg);
However, this is not allowed. And neither is:
Function<typeof(SomeType)>(arg);
I am far from a C# expert so excuse if this is a stupid question. But why doesn't this work? And how can I work around it to get similar functionality?
Since you can't accept a comment as an answer I just thought I would write it hear.
First Question: Why can't you pass the Type you get from fieldInfoInstance.FieldType to a generic function
If I have understood everything correctly, it is as #Lee pointed out, what is returned from fieldInfoInstance.fieldType is an instance of a class that extends type where as a generic function expects a Type Paramater.
Second Question: How can you work around not being able to do so?
I ended up doing like #silkfire and #Lee suggested, having a function that takes the type as an argument instead of an generic function. However I still prefer generic functions over casting when using a function so I ended up using two functions.
private static object Function(Type type, Arguments args)
{
// DO FUNCTION STUFF
}
and
public static T Function<T>(Arguments args)
{
return (T) Function(typeof(T), args);
}
This way the user can still call the function in a generic way, and by doing so doesn't have to cast the returned object (In my opinion alot cleaner) and I can call the function and pass in a Type. The non-generic function doesn't have to be public because the only time I need to pass the Type using a Type Instance instead of a Type Parameter is when recursively calling the function from within.
You can tell the compiler to force T to be the same as someFieldInfo.Field by passing in an expression (which is never used)
public static T Function<T>(Argument arg, Expression<Func<T>> anyField)
{
}
T result = Function(arg, () => someFieldInfo.Field);
But that's at compile-time. Generic types in C# have to be resolved at compile-time.
You wanted to use somefieldInfo.FieldType at run-time. For run-time types you cannot use generics, because you cannot predict what the type will be.
Instead cast the returned object at run-time using Convert.ChangeType.
public static object Function(Argument arg, Type anyFieldType)
{
object result = ...;
return Convert.ChangeType(result, anyFieldType);
}
object result = Function(arg, someFieldInfo.FieldType);
Related
I want to do all of the same code twice, but just for two different objects. I am getting these objects from a SOAP API (rather outdated one).
I want to avoid writing duplicate code over and over again. I'll be taking my original object and manipulating it a lot (all the same way) the only difference is that the object type is the difference, so that's why I need to make a generic object. I want it to return the same type as it takes as a parameter. I am having an issue that if I do code like this
public static class ParamsHelper<T>
{
public static async Task<T[]> Whatever(T[] rptParams)
{
//do some stuff to rptparams
return rptParams;
}
}
// then I call it like this below:
var params = await ParamsHelper.Whatever<ItemP[]>(new ItemP[]{});
// it says can't convert type ItemP[] to type ItemP[][].
Additionally, I am using LINQ to do all of the manipulating. I would love advice on how to access the object fields (maybe reflection?)
You have to declare the generic type on the method.
public static async Task<T[]> Whatever<T>(T[] rptParams)
The usage generally is implied from usage so you don't have to pass it.
if you do have to pass it, dont make it an array.
ParamsHelper.Whatever<ItemP>(new ItemP[] { });
[edit] the following works in C#
public class C {
public void M() {
Func<int,string> a = intArg => "helloWorld"; // string:object
Test(a);
Func<int,C> b = intArg => new C(); // C:object
Test(b);
}
public void Test(Func<int,object> arg){
Console.WriteLine(arg(1).ToString());
}
}
how can I achieve the same thing with self declared delegate?
public class C {
public delegate Y MyDelegate<X,Y>(X input);
public void M() {
MyDelegate<int,string> a = intArg => "helloWorld"; // cannot convert from 'C.MyDelegate<int, string>' to 'C.MyDelegate<int, object>'
Test(a);
MyDelegate<int,C> b = intArg => new C(); // cannot convert from 'C.MyDelegate<int, C>' to 'C.MyDelegate<int, object>'
Test(b);
}
public void Test(MyDelegate<int,object> arg){
Console.WriteLine(arg(1).ToString());
}
}
I understand that the compiler cannot tell which type argument is for parameter (contravariance) and which is for return value (covariance), maybe there is way to specify it?
[update]
I have found my solution:
public delegate Y MyDelegate<X,out Y>(X input);
When you call this:
object delegateArg = genericMethod.Invoke();
The return value - delegateArg - is a Func<int, something>, where something could be anything. And then you want to pass that Func<int, ???> to another method which will presumably invoke it.
You can pass that it to a method that expects Func<int, object> and it will compile unless the second generic argument is a value type. When you invoke it, you'll get the result of the invocation cast as an object. The actual type of the result will be whatever that second unknown generic argument is.
But if you don't know what that second generic argument is, then the method you pass it to isn't going to know either. The only way it could find out is by using reflection, inspecting the type, and getting the second generic argument.
So you could pass in a Func<int, object> and do some reflection to find out that the object is really a string. Or you could just invoke the function, get the result, and check the type of the returned value and determine that it's a string.
The big problem is that if you don't already know what type you're going to get, how do you know what you want to do with it? If you don't know what type genericMethod.Invoke is going to return with any more certainty, then how do you know you want it at all?
It's a bit like going to the store to buy a wall-mount bracket, except you don't know what it is that you want to mount on a wall. But if you don't know what it is that you want to mount, then why are you going to the store to buy a wall mount bracket?
Sometimes there are good reasons, but this is often what happens when we have functions that return something non-specific and then pass them to other methods. It's much better if we can work it out so that our code is strongly typed. We call a method that returns a certain type because we want an object of that type. Then we pass that thing to another method that expects that type and has a specific use for it.
There are exceptions and cases where we don't really care what the type of something is, but it's less common because we don't usually write code that isn't meant to do something specific with something specific. Unless we're certain that we really don't care what the actual type is, it's good to revisit our approach and find a way to make it strongly typed. That can involve using generics or in some cases writing more classes or methods instead of one that handles a variety of inputs.
Say you have this generic method:
public static T ConvertValue<T, U>(U value) where U : IConvertible
{
return (T)Convert.ChangeType(value, typeof(T));
}
If I want to call this method inside another generic method. The outer generic method must receive as arguments the actual argument values to set <T, U>(U value) of the inner generic method.
How to achieve this properly, so that I can call OuterGeneric and feed it with the appropriate arguments?
This is just a demonstration of how I need to use it.
public void OuterGeneric<TypeT, TypeU>(TypeT tType, TypeU uType, TypeU valueOfTypeU)
{
// Call of Generic method
TypeT recieverOf_T = ConvertValue<tType, uType>(valueOfTypeU);
}
// Some way to call OuterGeneric. How?
Just call ChangeType directly. You're wrapping the call in a method that requires the type to be specified at compile time, rather than runtime, and then asking how to call it when the type is only known at runtime. You already had a method (ChangeType) that does exactly that.
You don't need method parameters for the generic types in your outer method. You should be able to just use the type parameters like this:
public void OuterGeneric<TypeT, TypeU>(TypeU valueOfTypeU)
{
// Call of Generic method
TypeT recieverOf_T = ConvertValue<TypeT, TypeU>(valueOfTypeU);
}
Then call OuterGeneric the way you would any other generic method.
Your question is a little unclear because you used the term "dynamically." Of course generic parameters must be known at compile time, so if you're looking for a way to use generic methods when only knowing the types at runtime, then you don't actually want to use .NET generics.
I want to implement a method that will find stuff in my custom class. It should work like generic collections work - i pass a pointer to a function, and the method will iterate through all it has to look in, apply this function, and if it returns true return the found item.
I'd like to pass function pointer as a parameter, but i dont want to declare delegate types.
I know i can do something like:
delegate bool Foo(MyClass)
MyClass MyMethod(Foo x)
{...}
And i know i can do something like this:
MyClass MyMethod(Func<MyClass,bool> x)
But can i do it without declaring a delegate type and without using built in stuff like Func<> which has limits on how many parameters i can have (in case of Func, one...)
You can just use delegate if you want, although it's a bit old school :)
public void TestInvokeDelegate()
{
InvokeDelegate( new TestDelegate(ShowMessage), "hello" );
}
public void InvokeDelegate(TestDelegate del, string message)
{
del(message);
}
public delegate void TestDelegate(string message);
public void ShowMessage(string message)
{
Debug.WriteLine(message);
}
You can allways pass in a Delegate and call DynamicInvoke on it:
MyClass MyMethod(Delegate x) {
// ...
x.DynamicInvoke(....);
// ...
}
It looks like you are trying to implement the Visitor pattern. In this case visiting methods usually have only one parameter - the instance to visit. Having additional arguments passed around conceals the use of the pattern and makes it harder to reason about. This article shows you one way to implement it in C#.
The key is to create a visitor class that will encapsulate all the parameters that affect the visiting process. This way you don't need to pass anythnig other than an object in question in the visiting method - everything else lives in instance fields.
However, if you really want to pass some additional parameters in the method and don't know what type they can have, there are ways to do that. More or less standard approach in .NET world is to use a delegate without return value and with single parameter of type object, the example would be ParameterizedThreadStart delegate:
public delegate void ParameterizedThreadStart(
Object obj
)
This way you get to pass only one parameter in the delegate, but it could be anything - an instance of a class, an array or null, if you end up not needing additional arguments after all. The downside of this approach is that it requires type casting which can lead to runtime errors.
How to invoke Display method extending object class?
static class Tools
{
public static void Display<T>(this T t)
{
Console.WriteLine("generic: " + t.GetType());
}
public static void Display(this object o)
{
Console.WriteLine("object: " + o.GetType());
}
}
class Program
{
static void Main(string[] args)
{
int i = 100;
// all will invoke the generic version.
Tools.Display<int>(i);
i.Display();
Tools.Display(i);
}
}
I can't remember where in the standard it says it, but C# prefers to call the most specific overload. With generics, the generic version of the function will almost always take preference. So while an int is an object, it better fits the Display<T>(T) than Display(object), since the realization of the generic (Display<int>(int)) is an exact match. Add the fact that C# can figure out which type belongs in the T by itself and you see the behavior you're experiencing.
So, you must explicitly cast to an object to call the object version:
((object)i).Display();
Alternatively:
Tools.Display((object)i);
And you'll have a curious (but sensible) issue if you do:
object o = 5;
o.Display();
o.Display<object>();
This will call the object version in the first case and the generic one in the second. Fun times with parameters!
Since i is an int, the generic overload is a better match than the one taking an object. If you cast i to object, the non-generic version will be invoked.
The Display Method is redundant. You actually do not need both the methods together.
First let me explain why it always executed the Generic version over the other.
The C# compiler will find the best type-match for a method call. Here in all the calls, the generic method turns out to be the best match because generic version's type argument will always be the same as what given in the call.
so for Tools.Display(i) call compiler will prefer the generic version because that is the best option based on the type-match.
Even in the other calls, the type is inferred from the argument and hence the generic version is preferrably called over the other.