Generic Delegate casting - c#

[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.

Related

make method in C# that takes function without type parameters

My eventual aim is to get a function that can take any other function - eg something like
void RegisterHandler( Delegate function);
however - I want to be able to call it without doing any casting, or without type parameters - obviously Delegate doesn't work. If I declare:
void RegisterHandler<T>( Func<T> function );
then it works fine - this works:
string Whatever() {return "hi";}
...
RegisterHandler( whatever );
however - as soon as I throw in parameters, it doesn't work
void RegisterHandler<TParam1,TReturn>( Func<TParam1, TReturn> function );
string Something( int x ) {return x.ToString();}
...
RegisterHandler( Something ); // doesn't compile - wants types specified
RegisterHandler<int,string>( Something ); // works, but is what I'm trying to avoid
I'd even be ok if "object" worked - this is just part of a fluent interface, and I just want to be able to call it. I read somewhere that the number of parameters has to be >= the number of template types, and I guess the return type is counted, so I can never fulfill that.
Bottom line - I can't find any c# signature that will accept any function that takes one parameter, and returns something. Is it possible?
Rather than attacking your problem directly, which needs some clarification, let me address your concerns here:
I read somewhere that the number of parameters has to be >= the number of template types
Let's crisp that up a bit.
First off, those are generic type parameters, not "template types". This isn't C++. Generics are similar to templates but they are not templates, and the sooner you stop thinking of them as templates, the better.
It is NOT true that the number of formal parameters needs to be greater than or equal to the number of generic type parameters declared by the generic method. For example:
static void M<K, V>(Dictionary<K, V> d) { }
...
Dictionary<int, string> d = whatever;
M(d); // No problem!
The number of formal parameters is one, the number of generic type parameters is two, but we have no problem doing type inference here.
The real rule is quite a bit more complicated. Rather, the real problem that you're running into is:
The conversion of a method group to a delegate requires that the parameter types of the delegate be known before the conversion happens.
Let's suppose we have:
int F(string x) { ... }
void M<A, R>(Func<A, R> f) { ... }
M(F);
What happens? We must determine what F means when converted to Func<A, R> but we know neither A nor R. How do we determine the meaning? We do overload resolution. That is, we would pretend that there was a call:
A a = whatever;
F(a)
and ask "which method named F would work?"
But we never even get to that step because we don't know what A is yet. Type inference fails to make progress. Now, if by contrast you had:
int F(string x) { ... }
void M<A, R>(A a, Func<A, R> f) { ... }
M("abc", F);
Now type inference first says "I deduce from the use of "abc" for a that A is string." After that inference is made, now overload resolution would succeed. If we did
string a = whatever;
F(a);
then overload resolution would determine that F means int F(string).
Once we have determined that F means int F(string), now we can ask the question "what can we deduce about the conversion from int F(string) to Func<string, R>, and from that we deduce R must be int and we're done.
I know what you're going to ask next. I only have one overload called F, so why don't we just pick it automatically?
There are many problems with making exceptions like that. First, special cases tend to multiply, and soon we have an even crazier inference algorithm that no one understands and it cannot be changed without causing bugs. Second, it makes your code brittle; it means that inference depends on the number of accessible methods named F in scope. Suppose you add a new private method also called F; does inference suddenly change?
No, the rule is straightforward and understandable once you know it. Method groups are resolved exactly the same as though there was a call to the method. But we cannot simulate a call until after the argument types are inferred.
Believe me, I know as well as anyone how tricky the type inference algorithm can be in C#; it has a lot of these sorts of surprising cases. If you have a more crisp question about the design, implementation or specification of this algorithm feel free to open up a new question and leave me a comment on this answer and I will try to have a look.
Are... you looking for Action?
Func<T> is a .net delegate that is meant to return a value.
Action is a .net delegate that does not return a value
Action<T> also accepts up to 16 params.

What is the value being passed into this lambda expression?

Forgive me if this is a stupid question but I am not sure where to look. I have this code that compiles fine:
static int Main(string[] args)
{
var parserResult = CommandLine.Parser.Default.ParseArguments<Options>(args);
parserResult.WithParsed<Options>(options => OnSuccessfulParse(options));
parserResult.WithNotParsed<Options>(errs =>
{
var helpText = HelpText.AutoBuild(parserResult, h =>
{
return HelpText.DefaultParsingErrorsHandler(parserResult, h);
}, e =>
{
return e;
});
Console.WriteLine(helpText);
ReturnErrorCode = ErrorCode.CommandLineArguments;
});
return (int)ReturnErrorCode;
}
My query has to do with this line of code:
parserResult.WithParsed<Options>(options => OnSuccessfulParse(options));
I understand that with a Lambda Expression the value on the left of the => is the value and value on the right is the expression.
What exactly is options? Why does it compile? It works absolutely fine. But what is it?
I don't know if this helps:
I might be barking up the wrong tree with my understanding of this. I admit I am struggling with the concept. Any explanation appreciated.
I see several questions but I can't explain it in my situation.
Update
OnSuccessfulParse declaration is:
private static void OnSuccessfulParse(Options options)
The WithParsed code is provided here
Lambda expression is the delegate of type Action<Options>. It is a callback from the parser into your code to inform you that the parse has been successful, and pass you Options object obtained as the result of the parse.
As far as options goes, it's just a name that you picked for the parameter to be passed into OnSuccessfulParse method. It is completely unnecessary here - this method group equivalent call will compile and run just the same:
parserResult.WithParsed<Options>(OnSuccessfulParse);
Here is the definition of WithParsed<T> method from github project:
public static ParserResult<T> WithParsed<T>(this ParserResult<T> result, Action<T> action)
{
var parsed = result as Parsed<T>;
if (parsed != null) {
action(parsed.Value);
}
return result;
}
This method is rather straightforward: it takes parse result, tries casting it to a successful parse, and if the cast is valid, calls a delegate that you supply. The WithNotParsed<T> method casts to unsuccessful NotParsed<T> result, and makes a call if the cast is valid.
That's a C# (.Net) way of representing function blocks.
Essentially an Action<Type> is an invocable type that roughly means pass an instance of Type in and execute the block.
E.g. we can write
public void Do(){
this.CallStuff(s => Console.WriteLine(s)); // or you can use a method group and do this.CallStuff(Console.WriteLine);
}
public void CallStuff(Action<string> action){
var #string = "fancy!";
action(#string);
}
In this case the s type is string.
In your example there is a type called Options defined somewhere and it is passed into an action.
Additionally, if you look at decompiled code, anonymous method blocks passed to actions are compiled as static anonymous types inside your class (because c# does not support dynamic code blocks, like, for example, obj-c does).
Another thing to look into are Func<out type> -> these are essentially the same as Action<> except the LAST type in the generic definition is the type they return.
UPD
#elgonzo raises a good point - Action<> and Func<> are actually just delegates; meaning that you can define a real method and pass it along as an Action or Func and then no anonymous static class will be compiled.
However in practice you will see that a lot of code defines those inline, and then the in-line code block needs to reside within a method somewhere, so the compiler puts it into the statis anonymous class.
What exactly is options?
options is i/p parameter to delegate represented by lambda expression
Why does it compile?
Simply because it adheres all syntactical and semantic rules of compiler ;) Like (x)=>x+1 is lambda expression to represent Func<int,int> (there can be another delegate to match same signature as well)
If your method expects Func<int,int> as parameter and argument passed is (x)=>x+1 then compiler infers this as x of type int. Compiled IL code would be equivalent to passing instance of delegate as an argument to method. Like :
call((x)=>x+1) will be compiled to call(new Func<int,int>(myMethod)) where call method definition is :
void Call(Func<int,int> someparam) {}
But what is it?
I think above response should have addressed this query.

Alternative to SomeFunction<SomeType.GetType()>(SomeArgument)

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);

casting from a var type to a different class

casting a var type objects to array of a class.
in my example I can query from the table all elements. but the problem is when i cast it, it just doesnt cast all instances.
any help??
There's no such type as "a var type". A declaration using var just makes the compiler infer the type of the variable. It's still statically typed, and works as if you'd explicitly declared it - although it allows you to declare variables which use an anonymous type.
In your case we don't know what any of the methods involved do, which means we can't really tell what's going on. It sounds like Query is probably of type IEnumerable<AccessPointItem>. You'll need to express in code how to convert from an AccessPointItem to an AccessPoint.
A few points to note:
Your query expression is somewhat pointless - you probably just want to call tsvc.CreateQuery<AccessPointItem>()
Conventionally, local variables in C# use camel casing (starting with lower case letters) not Pascal case
You create an array for no purpose - why?
Select() will never return null, so you don't need to check for it
Calling Cast will attempt to just cast each AccessPointItem to AccessPoint... is that really what you intended?
It looks as though you're you're mixing up your classes AccessPoint and AccessPointItem. Try this:
public static AccessPoint[] getAllAps()
{
return tsvc.CreateQuery<AccessPoint>("AccessPointTable").ToArray();
}
or this:
public static AccessPointItem[] getAllAps()
{
return tsvc.CreateQuery<AccessPointItem>("AccessPointTable").ToArray();
}
There is something wrong with the types involved.
First you read AccessPointItem:
var Query = from APs in tsvc.CreateQuery<AccessPointItem>(...)
Then you try to cast it to AccessPoint:
return Query.Cast<AccessPoint>()
You're gonna need to implement some kind of conversion method in order for that to work (unfortunately I never did it myself, but from a quick Google run I see plenty of info about the subject is available). I'll give it a shot off the top of my head:
//inside AccessPointItem.cs
public static AccessPoint ToAccessPoint(this AccessPointItem item) // extension method looks good for the job
{
AccessPoint retObj = new AccessPoint();
// assign properties from 'item' to 'retObj'
return retObj;
}
//Usage example in your case
return Query.Select(singleAccessPointItem => singleAccessPointItem.ToAccessPoint());

C# function that takes pointer to function as an in parameter without declaring any specific delegate types?

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.

Categories