I am wondering how I can fetch the incoming arguments of my method in an array. Or just retrieve the values of my arguments dynamically.
Meaning, a call like:
MyMethod(10, "eleven");
For method:
void MyMethod(int Test, str Test2) {}
Would resolve in an array like:
{{"Test" => 10}, {"Test2", "eleven"}}
Would be even better if I could achieve this with reflection.. Ex. somehow with StackTrace.
I think, what you are looking for does not exist. The closest you can have is params:
MyMethod(params object[] args)
{
// if you have to do this, it's quite bad:
int intArg = (int)args[0];
string stringArg = (string)arg[1]:
}
// call with any number (and type) of argument
MyMethod(7, "tr");
There is no compile time type checking, and therefore it is not an all-purpose way to handle arguments. But if your arguments are dynamic, it's probably a solution.
Edit: had another idea:
You need to put all argument manually into a list / dictionary. You can write a helper class to allow the following:
MyMethod(int arg1, string arg2)
{
Arguments.Add(() => arg1);
Arguments.Add(() => arg2);
//
}
The helper looks like this
public static void Add<T>(Expression<Func<T>> expr)
{
// run the expression to get the argument value
object value = expr.Compile()();
// get the argument name from the expression
string argumentName = ((MemberExpression)expr.Body).Member.Name;
// add it to some list:
argumentsDic.Add(argumentName, value);
}
Your best option is to do it with an anonymous type, as shown in this example.
Nice Question (+1). I think this is what you need -
MethodBase mb = MethodBase.GetCurrentMethod();
ParameterInfo[] pi = mb.GetParameters();
One way I know (not sure if it's the only way nowadays, but it used to be) is to use aspect-oriented programming (AOP), and in particular interception. It is a bit painful to roll it by hand, but there are excellent tools that come to the rescue. One such tool is PostSharp: http://www.postsharp.org/.
Since the method is using named parameters, why can't you just explicitly populate a dictionary with their names and values? There is little point in using reflection to get their names since you already know them.
As already stated, the params keyword can be used to define a method with a variable number of parameters, but by definition those are nameless.
I'm not sure what you are asking, in the way you've explained it, makes any sense. Perhaps you could elaborate further?
Maybe this won't be exactly what you were looking for, but I found I could get a reasonable compromise for my situation using a variation on the method Matt Hamilton suggested and making use of the implicit naming of anonymous type parameters:
public void MyMethod(string arg1, bool arg2, int arg3, int arg4)
{
var dictionary = new PropertyDictionary(new
{
arg1, arg2, arg3, arg4
});
}
public class PropertyDictionary : Dictionary<string, object>
{
public PropertyDictionary(object values)
{
if(values == null)
return;
foreach(PropertyDescriptor property in TypeDescriptor.GetProperties(values))
Add(property.Name, property.GetValue(values);
}
}
As I said, it may not be helpful in your situation, but in mine (unit testing a method which processes XML) it was very useful.
Related
I want to write a function that takes a function as an argument and then do different things based on whether the passed-in function returns void vs a value.
C# signature checking can't tell the difference so I'm stuck doing it in code.
Is there an easy way to test whether an arbitrary function returns void?
To be clear. I explicitly am not interested in a compile error. I just want the equivalent of what I can do for any other object.
void IsString(object o) => o is string;
void ElseWhere() {
object o = 1;
if (IsString(o)) Bla();
However even this gets a compile error claiming the two methods are ambiguous. It doesn't flag the methods themselves ambiguous but I get an error on the call saying it can't resolve between them.
private static bool HasNoReturnValue(Action o) => true;
private static bool HasNoReturnValue(Func<object> o) => false;
...
if (HasNoReturnValue(SomeFunction)) Bla();
As do anything I've tried involving typeof:
if (SomeFunction is typeof(Func(object>)) Bla();
Let's say you have two methods, one of which returns a Boolean and one which returns void.
void SomeFunction1()
{
}
bool SomeFunction2()
{
return false;
}
To pass either of these as a pointer to a method, you have to convert them to a delegate. Two types of delegates: Action and Func<bool>, respectively:
var action1 = new Action(SomeFunction1);
var action2 = new Func<bool>(SomeFunction2);
You can then write two methods that accept these types as arguments:
void AcceptDelegate(Action action)
{
Console.WriteLine("The delegate returns void.");
}
void AcceptDelegate(Func<bool> func)
{
Console.WriteLine("The delegate returns a Boolean.");
}
And call them like this:
AcceptDelegate(action1);
AcceptDelegate(action2);
Or you could pass the method group directly and the compiler will figure out the type (Why? See the Microsoft documentation on c# method group conversions):
AcceptDelegate(SomeFunction1);
AcceptDelegate(SomeFunction2);
Either way you call them, you would get this output:
The delegate returns void.
The delegate returns a Boolean.
The reason this works is the compiler will automatically pick the right one at compile-time, based on the type of the delegate, just as it would pick the overload for any type such as string or integer. This is the type-safe / early-bound way to do it.
If you insist on an "any delegate"/ late binding sort of approach, you could do something like this:
void AcceptAnyDelegate(Delegate anyAction)
{
Console.WriteLine("The function returns a {0}", anyAction.Method.ReturnType);
}
Because the signature isn't type specific, you have to pass the specific delegates this time (Why? See this answer):
AcceptAnyDelegate(action1);
AcceptAnyDelegate(action2);
And the output would be:
The function returns a Void
The function returns a Boolean
Edit
After rereading your comments, I believe the confusion here is due to a misunderstanding of method groups and delegates.
When you write something like this:
Foo(Bar);
...it appears you believe you are passing to Foo a direct reference to the Bar method. That is not correct. What you are doing is specifying a method group, which the compiler can then use to infer the type of delegate to pass. If Bar is a method with no inputs or outputs, the above code is exactly the same as
Foo(new Action( Bar ));
...only the creation of the delegate is hidden from you by the compiler.
All delegates are specifically typed with respect to their parameters and return type. The Delegate base type is abstract and cannot exist in concrete form. So there is no such thing as passing a type-agnostic function reference-- it doesn't exist in c#.
If you really really want to pass something that is type-agnostic, you can ask the caller to pass a lambda expression:
Foo( () => SomeFunction1() );
You could then parse the expression to figure out the method's inputs and outputs:
void Foo(Expression<Action> anyAction)
{
var mce = anyAction.Body as MethodCallExpression;
var method = mce.Method;
Console.WriteLine("The method has a return type of {0}", method.ReturnType.Name);
}
Then to invoke the expression you would use:
var compiled = anyAction.Compile();
compiled();
That is the closest you're going to get.
There's two different types here:
Action for no return type
and
Func for a return type
Can you make two different signatures for these two different argument types?
This will do the trick
public static void TakeInAFunc<T>(T aFuncOrAction)
{
if (typeof(T) == typeof(Func<>))
{
// some value returned.
}
else if (typeof(T) == typeof(Action<>))
{
// it returns void.
}
}
I have a list of Action<object, object> and I end up getting this back into an Action<string, int> at some point, or any other two types. It represents a dynamic referential mapping from one type to another. For various reasons, I cannot use ref or Func<..>.
Basically the issue is that inside the callback code for that Action<string, int> I need a way to set the value of the int that is passed in, say after I convert it from a string. Though since it is not ref, it's not obvious how to do it.
Does anyone happen to know if there is a way to rewrite the method dynamically or otherwise get at the value that is passed into it (up the stack perhaps) and set the int value... one step up the CLR call stack?
To head off anyone saying "Why not change your whole program" or "When would you ever need this?", I am simply experimenting with the idea of a new kind of object mapping library.
Interesting question, I would very much like to know the root answer!
So far, my best approach is to create your own delegate, and wrap them in generic
delegate void MyAction<T,T1>(ref T a, T1 b);
static void Main(string[] args)
{
MyAction<string, int> action = Foo;
var arr = new object[] { "", 5 };
action.DynamicInvoke(arr);
}
private static void Foo(ref string a, int b)
{
a = b.ToString();
}
Not possible with value types. They are always copied on the stack and in case of boxing (for every boxing that is encountered) they are moved to a new location in heap and a reference is passed back.
You can try and wrap your int into a reference type and take advantage of side effects (since this is exactly what you are trying to do. Or you can keep the int parameter and store the result on a closed variable. E.g.: (string str, int i) => { myDictionary.Add(str, i); }.
This may have been answered before. I see many "dynamic method overload resolution" questions, but none that deal specifically with passing a dynamic argument. In the following code, in Test, the last call to M cannot be resolved (it doesn't compile). The error is: the call is ambiguous between [the first two overloads of M].
static void M(Func<int> f) { }
static void M(Func<string> f) { }
static void M(Func<dynamic> f) { }
static dynamic DynamicObject() {
return new object();
}
static void Test() {
M(() => 0);
M(() => "");
M(() => DynamicObject()); //doesn't compile
}
Why, since the type isn't statically known, does it not resolve to the overload accepting dynamic?
Is it even possible for an overloaded method to use dynamic?
What is the best way to resolve this?
The problem here is type inference. The compiler is trying to find out which overload to use based on the argument, but it's also trying to find out what the type of the argument is based on the chosen overload. In the case of M(() => DynamicObject()), the process goes something like this:
The argument to the method is a lambda with zero parameters. This gives us all three overloads as possibilities.
The body of the lambda returns dynamic. Because there is an implicit conversion from dynamic to any other type, we now know all three overloads are good.
Try choosing the best overload. In most cases, “best” means the most derived type. Because both int and string derive from object, the overloads with int and string are considered best.
We now have two “best” overloads, which means the compiler can't actually choose one of them. The compilation fails.
Now, regarding possible solutions to your problem:
Make the type of the lambda explicit, either using cast or typed local variable:
M((Func<dynamic>)(() => DynamicObject()));
or
Func<dynamic> f = () => DynamicObject();
M(f);
Rename the dynamic overload to something like DynamicM. This way, you don't have to deal with overload resolution.
This one feels somewhat wrong to me: make sure the dynamic overload is the only one that fits, by casting to object:
M(() => (object)DynamicObject())
From the definition in MSDN:
dynamic
Type dynamic behaves like type object in most circumstances. However,
operations that contain expressions of type dynamic are not resolved
or type checked by the compiler. The compiler packages together
information about the operation, and that information is later used to
evaluate the operation at run time. As part of the process, variables
of type dynamic are compiled into variables of type object. Therefore,
type dynamic exists only at compile time, not at run time
So dynamic doesn't exist when you compile, cause it needs to convert it into destination *type*, and that's why is not able to resolve it. What is destination type ?
In fact if you do something like this:
static void M(Func<int> f) { }
static void M(Func<string> f) { }
static void M(Func<object> f) { } // could be also declared like dynamic here, works by the way
static object DynamicObject()
{
return new object();
}
static void Test()
{
M(() => 0);
M(() => "");
M(() => DynamicObject());
}
It perfectly works as you want, as object is present like a type already at compile time, in difference of dynamic type which have to be converted.
Often you want to send multiple values but due to low use (i.e. it is only used in one or two places), it's hard to justify creating a new type.
The Tuple<...> and KeyValuePair<,> type are very useful, but there isn't real language support for them.
Well sort of, a nice trick to use for Lists of tuples is to create a type that extends the List and adding a custom add method:
e.g.
public class TupleList<T1,T2> : List<Tuple<T1,T2>>{
public void Add(T1 key, T2 value){
base.Add(Tuple.Create(key, value));
}
}
This means that if I have a method that takes an IEnumerable<Tuple<int,string>>, I can use the following code to quickly build up the list like so::
Foo(new TupleList<int,string>{{1,"one"},{2,"two"},{3,"three"}});
This makes winding values into a tuple list easier as we don't have to constantly keep saying Tuple.Create, and gets us almost to a nice functional languages syntax.
But when working with a tuple it is useful to unwind it out into its different components. This extension method might be useful in this respect::
public static void Unwind<T1,T2>(this Tuple<T1,T2> tuple,out T1 var1,out T2 var2)
{
var1 = tuple.Item1;
var2 = tuple.Item2;
}
But even that's annoying as out parameters are not variant at all. That is if T1 is a string, I can't send in an object variable even though they are assignable, when as I can do the unwinding by hand otherwise. I can't really suggest a reason why you might want this variance, but if its there, I can't see why you would want to lose it.
Anyone have other tips to making working tuples, or tuple like objects easier in C#?
An important potential use for tuples might be generic memoization. Which is very easy in languages like F#, but hard in C#.
I'm currently using Tuples to supply a MethodBase and an array of tokens (constants, objects, or argument tokens), supplied to a dynamicly built object to construct certain member fields.
Since I wanted to make the syntax easier on API consumers, I created Add methods that can take a ConstructorInfo or a MethodInfo and a params array of objects.
Edit:
Eric Lippert as usual has excellent motivation for using Tuples here and he even says what I suspected there really is no support:
What requirement was the tuple designed to solve?
In C# you can alias closed generic types, which Tuple is, this enables you to provide some better insight to what is intended. Doesn't change code much, but if you look at the example below the intent of what GetTemp is returning is better.
Without alias:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var result = GetTemp(10, 10);
Console.WriteLine("Temp for {0} is {1}", result.Item2, result.Item1);
}
// You give a lat & a long and you get the closest city & temp for it
static Tuple<double, string> GetTemp(double lat, double #long)
{
// just for example
return Tuple.Create(10d, "Mordor");
}
}
}
With alias:
namespace ConsoleApplication1
{
using CityTemp = Tuple<double, string>;
class Program
{
static void Main(string[] args)
{
var result = GetTemp(10, 10);
Console.WriteLine("Temp for {0} is {1}", result.Item2, result.Item1);
}
// You give a lat & a long and you get the closest city & temp for it
static CityTemp GetTemp(double lat, double #long)
{
// just for example
return new CityTemp(10, "Mordor");
}
}
}
Use Mono! They have experimental support for binding variables to tuple members so you could call a method like
Tuple<string, string, string, int, string> ParseUri (string url);
using code like
(user, password, host, port, path) = ParseUri (url);
There will be an awesome tuple feature coming with c#7 / visual studio 15.
basically you can do soething like that
static (int x, int y) DoSomething()
{
return (1, 2);
}
static void Test()
{
var cool = DoSomething();
var value = cool.x;
}
Read according post
In C# I am trying to write code where I would be creating a Func delegate which is in itself generic. For example the following (non-Generic) delegate is returning an arbitrary string:
Func<string> getString = () => "Hello!";
I on the other hand want to create a generic which acts similarly to generic methods. For example if I want a generic Func to return default(T) for a type T. I would imagine that I write code as follows:
Func<T><T> getDefaultObject = <T>() => default(T);
Then I would use it as
getDefaultObject<string>() which would return null and if I were to write getDefaultObject<int>() would return 0.
This question is not merely an academic excercise. I have found numerous places where I could have used this but I cannot get the syntax right. Is this possible? Are there any libraries which provide this sort of functionality?
Well you can't overload anything based only on the return value, so this includes variables.
You can however get rid of that lambda expression and write a real function:
T getDefaultObject<T>() { return default(T); }
and then you call it exactly like you want:
int i=getDefaultObject<int>(); // i=0
string s=getDefaultObject<string>(); // s=null
Though one might find practical workarounds like Stephen Cleary's
Func<T> CreateGetDefaultObject<T>() { return () => default(T); }
where you can specify the generics directly, this is a quite interesting problem from a theoretical point that cannot be solved by C#'s current type system.
A type which, as you call it, is in itself generic, is referred to as a higher-rank type.
Consider the following example (pseudo-C#):
Tuple<int[], string[]> Test(Func<?> f) {
return (f(1), f("Hello"));
}
In your proposed system, a call could look like that:
Test(x => new[] { x }); // Returns ({ 1 }, { "Hello" })
But the question is: How do we type the function Test and it's argument f?
Apparently, f maps every type T to an array T[] of this type. So maybe?
Tuple<int[], string[]> Test<T>(Func<T, T[]> f) {
return (f(1), f("Hello"));
}
But this doesn't work. We can't parameterize Test with any particular T, since f should can be applied to all types T. At this point, C#'s type system can't go further.
What we needed was a notation like
Tuple<int[], string[]> Test(forall T : Func<T, T[]> f) {
return (f(1), f("Hello"));
}
In your case, you could type
forall T : Func<T> getDefaultValue = ...
The only language I know that supports this kind of generics is Haskell:
test :: (forall t . t -> [t]) -> ([Int], [String])
test f = (f 1, f "hello")
See this Haskellwiki entry on polymorphism about this forall notation.
This isn't possible, since a delegate instance in C# cannot have generic parameters. The closest you can get is to pass the type object as a regular parameter and use reflection. :(
In many cases, casting to dynamic helps remove the pain of reflection, but dynamic doesn't help when creating new instances, such as your example.
You can't do this, because generic type parameters have to be known at runtime. You have to use the activator class:
Object o = Activator.CreateInstance(typeof(StringBuilder));
which will do exactly what you want to. You can write it as the following:
public T Default<T>()
{
return (T)Activator.CreateInstance(typeof(T));
}
Edit
Blindy's solution is better.