I am writing an asynchronous class to simplify function operation. Below is my code:
using System;
namespace AsyncLibery
{
public class AsyncLibery
{
delegate void Exec(); // No input parameter, no return value
delegate void ExecWithParams<T>(T T1); //One input parameter, no return value
delegate void ExecWithParams<T1, T2>(T1 t1,T2 t2); //Two input parameters, no return value
delegate void ExecWithParams<T1, T2, T3>(T1 t1, T2 t2, T3 t3);//Three input parameters, no return value
delegate void ExecWithParams<T1, T2, T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4);//Four input parameters,no return value
delegate T ExecWithReturnType<T>(); //No input parameter, one return value
delegate T2 ExecWithReturnType<T1, T2>(T1 t1); //One input parameter, one return value
delegate T3 ExecWithReturnType<T1, T2, T3>(T1 t1, T2 t2);//Two input parameters, one return value
delegate T4 ExecWithReturnType<T1, T2, T3, T4>(T1 t1, T2 t2, T3 t3);//Three input parameters, one return value
delegate T5 ExecWithReturnType<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4);// Four input parameters, one return value.
#region no input parameter, no return value
public void BeginInvokeEx(Action actionFunction)
{
Exec exec = new Exec(actionFunction);
exec.BeginInvoke(new AsyncCallback(EndInvokeEx), exec);
}
private void EndInvokeEx(IAsyncResult iar)
{
Exec exec = (Exec)iar.AsyncState;
exec.EndInvoke(iar);
}
#endregion
#region one input parameter, no return value
public void BeginInvokeEx<T>(Action<T> actionFunction,T T1)
{
ExecWithParams<T> exec = new ExecWithParams<T>(actionFunction);
exec.BeginInvoke(T1, new AsyncCallback(EndInvokeEx1), exec);
}
private void EndInvokeEx1(IAsyncResult iar)
{
ExecWithParams<T> exec = (ExecWithParams<T>)iar.AsyncState;
exec.EndInvoke(iar);
}
#endregion
}
}
When I complied the code, it throws me an exception like "The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)", the exception is appeared at below code :
ExecWithParams<T> exec = (ExecWithParams<T>)iar.AsyncState;
I know that we must refer T parameter the specific type like int or string or anything else.
But who can help me without modifying the T parameter? is there any good method to deal with it?
thx.
Make EndInvokeEx1 generic:
private void EndInvokeEx1<T>(IAsyncResult iar)
{
ExecWithParams<T> exec = (ExecWithParams<T>)iar.AsyncState;
exec.EndInvoke(iar);
}
And change your BeginInvokeEx accordingly:
public void BeginInvokeEx<T>(Action<T> actionFunction,T T1)
{
ExecWithParams<T> exec = new ExecWithParams<T>(actionFunction);
exec.BeginInvoke(T1, new AsyncCallback(EndInvokeEx1<T>), exec);
}
You haven't defined what T is. You need to either have a generic parameter on the method EndInvokeEx1 such that it becomes EndInvokeEx<T>, where you can then pass T to the cast. Otherwise, it will need to be defined in the class declaration, so your class declaration becomes public class AsyncLibrary<T>. Otherwise, the compiler won't know what T is meant to represent.
Related
I defined this method:
public static List<T2> ConvertList<T1, T2>(List<T1> param) where T1:class where T2:class
{
List<T2> result = new List<T2>();
foreach (T1 p in param)
result.Add((T2)p);
return result;
}
For converting Lists of Type 1 to Lists of Type 2.
Unfortunately I forgot, that C# compiler cannot say at this stage that T1 is convertible to T2, so it throws error:
error CS0030: Cannot convert type T1 to T2
Can someone direct me how to do it properly? I need this method for now only to convert list of custom class to list of object, so as in .NET everything derives from object it should work.
Basically what I would expect is some syntax to tell compiler that T2 (object) is base for T1 (MyClass), so something like:
public static List<T2> ConvertList<T1, T2>(List<T1> param) where T2: base of T1
(... where T2: base of T1)
You could specify it in a generic parameter:
public static List<T2> ConvertList<T1, T2>(List<T1> param)
where T1:class,T2
where T2:class
{
List<T2> result = new List<T2>();
foreach (T1 p in param)
result.Add((T2)p);
return result;
}
I need to call a method that receive a list of Func<T>, the problem is that the return of the Func is not the same for all the items of the list.
For example:
//Having the following method:
public void DoSomething(params Expression<Func<T>> list)
{
//get the property info to get the name and value
// PropertyInfo p = (propertyExpression.Body as MemberExpression).Member as PropertyInfo;
//EDIT: Using the answer to change the T to object I needed to get the property info using this:
(((UnaryExpression)propertyExpression.Body).Operand as MemberExpression).Member as PropertyInfo;
}
//and the following object
public class Foo
{
public long Id { get;set; } //LOOK: ITS A LONG PROPERTY
public string Name { get; set; } // ITS A STRING PROPERTY
}
//I would like to pass these two expressions of DIFFERENT returning types.
Foo f = new Foo();
DoSomething(() => f.Id, () => f.Name); //TWO RETURN TYPES DIFFERENTS.
The compiler says that it's impossible because the method param is a Generic Type T, so all the Funcs passed needs to be the of the same return type.
Use params Expression<Func<object>>[] list as a parameter, instead of T (note that it must be an array for using with params)
You will, of course, need to cast the result to work with it (unless your process can work with object... say to do a ToString(), for example) inside DoSomething, but how else were you expecting to work with T when T can be different depending on the parameter?
Update: I've made an example in this fiddle, but what you can do with this is pretty much limited, so as #juharr stated in the comments, it'd be better if you explained what do you want to do so we can suggest more practical alternatives
Also, if you don't need the expression (just the callback), there's no need to pass a expression, just pass the Func (modified fiddle)
OK, its not pretty, but I think this is the only way its going to work with generics. It probably not a practical solution:
public void DoSomething<T>(Expression<Func<T>> p)
{
}
public void DoSomething<T1,T2>(Expression<Func<T1>> p1,Expression<Func<T2>> p2)
{
}
public void DoSomething<T1,T2,T3>(Expression<Func<T1>> p1,Expression<Func<T2>> p2,Expression<Func<T3>> p3)
{
}
//etc...
Microsoft does the samae thing with its Func deligates
public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, inT7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, out TResult>(
T1 arg1,
T2 arg2,
T3 arg3,
T4 arg4,
T5 arg5,
T6 arg6,
T7 arg7,
T8 arg8,
T9 arg9,
T10 arg10,
T11 arg11,
T12 arg12,
T13 arg13,
T14 arg14
)
One possibility would be to use a fluent interface instead of a list
public object Command
{
public void DoSomething()
{
//do something, act on values stored in member var;
}
public Command AddProp<T>(Expression<Func<T>> propAndValue)
{
// Get property and value from expression
// store in member var
return this;
}
}
public class Foo
{
public long Id { get;set; } //LOOK: ITS A LONG PROPERTY
public string Name { get; set; } // ITS A STRING PROPERTY
}
// Example usage
Foo f = new Foo();
Command cmd = new Command();
cmd.AddProp(() => f.Id).AddProp(() => f.Name).DoSomething();
This question already has answers here:
Func<T> with out parameter
(4 answers)
Closed 9 years ago.
Func<a, out b, bool>, just don't compile, how to declare that i want the second parameter be an out one?
I want to use it like this:
public class Foo()
{
public Func<a, out b, bool> DetectMethod;
}
Actually, Func is just a simple delegate declared in the .NET Framework. Actually, there are several Func delegates declared there:
delegate TResult Func<TResult>()
delegate TResult Func<T, TResult>(T obj)
delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
delegate TResult Func<T1, T2, T3, TResult>(T1 obj1, T2 obj2, T3 obj3)
delegate TResult Func<T1, T2, T3, T4, TResult>(T1 obj1, T2 obj2, T3 obj3, T4 obj4)
delegate TResult Func<T1, T2, ... , T16, TResult>(T1 obj1, T2 obj2, ..., T16 obj16)
So the only thing you can do is declare your custom delegate:
delegate bool MyFunc<T1, T2>(T1 a, out T2 b)
You need to make your own delegate type, like this:
delegate bool MyFunc(Type1 a, out Type2 b);
You might want to rethink your design. Do you really need to complicate your code by adding an out parameter?
You can wrap the bool return type and the second out type in their own class (or .NET 4.0 Tuple) and use that as a return type:
public Func<Type1, Tuple<Type2, bool>> DetectMethod;
Of course when you want to use the delegates to reference try-parse methods, you are on the right track and you'll need to define a new delegate as others already described.
I have written a helper class which uses the Action - delegate as method parameter.
Like this:
public void SomeMethod(Action<T> methodToExecute, T argument);
According to the MSDN you can declare max. 4 arguments on an action delegate: Action<T1,T2,T3,T4>.
Now I'd like to call a method which needs 5! arguments. How could I do this?
The best solution would be something where I could use a dynamic number of method arguments.
Thanks
Declare the action delegate you need, there's nothing magic about it:
public delegate void Action<T1, T2, T3, T4, T5>(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5);
Can I pass a method with an out parameter as a Func?
public IList<Foo> FindForBar(string bar, out int count) { }
// somewhere else
public IList<T> Find(Func<string, int, List<T>> listFunction) { }
Func needs a type so out won't compile there, and calling listFunction requires an int and won't allow an out in.
Is there a way to do this?
ref and out are not part of the type parameter definition so you can't use the built-in Func delegate to pass ref and out arguments. Of course, you can declare your own delegate if you want:
delegate V MyDelegate<T,U,V>(T input, out U output);
Why not create a class to encapsulate the results?
public class Result
{
public IList<Foo> List { get; set; }
public Int32 Count { get; set; }
}
The Func family of delegates (or Action for that matter) are nothing but simple delegate types declared like
//.NET 4 and above
public delegate TResult Func<out TResult>()
public delegate TResult Func<in T, out TResult>(T obj)
//.NET 3.5
public delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
public delegate TResult Func<T1, T2, T3, TResult>(T1 obj1, T2 obj2, T3 obj3)
etc. Delegates as such can have out/ref parameters, so in your case its only a matter of custom implementation by yourself as other answers have pointed out. As to why Microsoft did not pack this by default, think of the sheer number of combinations it would require.
delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
delegate TResult Func<T1, T2, TResult>(out T1 obj1, T2 obj2)
delegate TResult Func<T1, T2, TResult>(T1 obj1, out T2 obj2)
delegate TResult Func<T1, T2, TResult>(out T1 obj1, out T2 obj2)
for just two parameters. We have not even touched ref. It would actually be cumbersome and confusing for developers.
You could wrap it in a lambda/delegate/function/method that exposed the right interface and called FindForBar, but I suspect that FindForBar has count as an out parameter as a reason, so you'd need to be sure throwing that information away was ok/safe/desirable/had the right results (you'd need to be sure of this even if you could just directly pass in FindForBar).