Can I avoid or optimize this dynamic invocation? - c#

I'm trying to write a class which can handle many different types of inputs, all of which implement the same interface.
I have the following code:
private IEnumerable<IPlan> DevisePlans(ITile tile, IEnumerable<ISpace> spaces)
{
MethodInfo method = GetType().GetMethod("DevisePlans",
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new[] {tile.GetType(), typeof(ISpace)},
null);
var type = typeof(Func<,,>).MakeGenericType(tile.GetType(), typeof(ISpace), typeof(IEnumerable<IPlan>));
var planner = Delegate.CreateDelegate(type, this, method);
return spaces.SelectMany(s => (IEnumerable<IPlan>)planner.DynamicInvoke(tile, s));
}
There are lots of various implementations of DevisePlans within the class, each with a first parameter type that implements ITile.
private IEnumerable<IPlan> DevisePlans(Foo tile, ISpace space) { /* ... */ }
private IEnumerable<IPlan> DevisePlans(Bar tile, ISpace space) { /* ... */ }
This works, but I'm calling DynamicInvoke for every single iteration of my enumerable. Even if I can't completely avoid the dynamic call, is there any way to optimize this method so that the dynamic invocation no longer resides within my loop?

It looks like you are using this to call the most specific overload (not override) of DevisePlans for the tile provided. Assuming my understanding is correct (please do tell me if I'm wrong), then just use dynamic - it has an inbuilt cache and is optimized for this:
return spaces.SelectMany(s =>
(IEnumerable<IPlan>)DevisePlans((dynamic)tile, (dynamic)s)
);
and... that's it!
I would, however, be tempted to look for an answer involving either polymorphism (against ITile) or C# 4.0 variance.

Create an expression tree (start with Expression.Call), compile it, and you'll have a fast delegate. You should cache the delegate based on the type so that you don't compile for the same type multiple times.

Think what you're looking for here is the visitor pattern. Define an ITileVisitor interface with your overload for each type and then ITile has a Visit method which takes the visitor as a parameter. Its the implementation of Visit which will cause the correct Devise overload to be called.

Related

Create an array containing a mix of method groups [duplicate]

I have a class that will require a varying number of Func delegates to be passed in the contructor. Each of these delegates will point to a different function, each with a different return type, and with a varying number of parameters (of type double). Each of these functions will then be called accordingly.
Question 1. Right now, to make things easier for those using this class, I am thinking about allowing the user to pass a List<object> of Func delegates. Is this possible, and if so am I able to determine the return type and number of params required for each Func in the method in which the List<object> is passed to (i.e. the constructor) ?
Question 2. If the above is not feasible, will I need to overload the constructor with every different combination of return types/number of params and route each Func accordingly -_- ... if not can someone point me in the right direction, I feel like i'm approaching this in the wrong way ...
note - coming from a python background, I would do something like this (i'm inexperienced in c#):
import inspect
def test(x): return x
inspect.getargspec(test)
returns: ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
Many thanks
Question 1. Right now, to make things easier for those using this class, I am thinking about allowing the user to pass a List of Func delegates. Is this possible, and if so am I able to determine the return type and number of params required for each Func in the method in which the List is passed to (i.e. the constructor) ?
Not really. You could allow a List<Delegate> (or some other collection with an element type of Delegate), but nothing Func-specific, for two reasons:
Func is effectively a family of types, with different number of generic type parameters. These types are entirely separate as far as the CLR is concerned; Func<TResult> and Func<T, TResult> are as different as Action<T> and EventHandler.
Even if you were only dealing with several values of the same generic type of delegate, the fact that they could have different type arguments means they're different types to the CLR; there's no way of saying List<Func<>> for "a list of functions with potentially varying type arguments". Again, the CLR treats them as separate types - although this time at least one with a common generic type definition.
Question 2. If the above is not feasible, will I need to overload the constructor with every different combination of return types/number of params and route each Func accordingly
Well, there are several options:
Make all the parameters optional, giving each of them a default value of null, then use named arguments when calling the constructor:
var foo = new Foo(clickHandler: () => ...,
keyHandler: key => ...);
Create a builder, so that the various functions can be set as properties - this works very well with the object initializer syntax:
var foo = new Foo.Builder {
ClickHandler = () => ...,
KeyHandler = () => ...
}.Build();
Both of the latter solutions depends on you really having a specific named purpose, of course.
It would help if you could be clearer about what you're trying to achieve - as dtb says, polymorphism may be a better fit here. You could create an abstract class with no-op implementations of virtual methods, and implementations could choose which ones to override.

How to use existing method instead of lambda when it's not static?

This must be a duplicate but i haven't found it. I've found this question which is related since it answers why it's recommended to use a method group instead of a lambda.
But how do i use an existing method group instead of a lambda if the method is not in the current class and the method is not static?
Say i have a list of ints which i want to convert to strings, i can use List.ConvertAll, but i need to pass a Converter<int, string> to it:
List<int> ints = new List<int> { 1 };
List<string> strings = ints.ConvertAll<string>(i => i.ToString());
This works, but it creates an unnecessary anonymous method with the lambda. So if Int32.ToString would be static and would take an int i could write:
List<string> strings = ints.ConvertAll<string>(Int32.ToString);
But that doesn't compile - of course. So how can i use a method group anyway?
If i'd create an instance method like this
string FooInt(int foo)
{
return foo.ToString();
}
i could use strings = ints.ConvertAll<string>(FooInt);, but that is not what i want. I don't want to create a new method just to be able to use an existing.
There is an static method in the framework, that can be used to convert any integrated data type into a string, namely Convert.ToString:
List<int> ints = new List<int> { 1 };
List<string> strings = ints.ConvertAll<string>(Convert.ToString);
Since the signature of Convert.ToString is also known, you can even eliminate the explicit target type parameter:
var strings = ints.ConvertAll(Convert.ToString);
This works. However, I'd also prefer the lambda-expression, even if ReSharper tells you something different. ReSharper sometimes optimizes too much imho. It prevents developers from thinking about their code, especially in the aspect of readability.
Update
Based on Tim's comment, I will try to explain the difference between lambda and static method group calls in this particular case. Therefor, I first took a look into the mscorlib disassembly to figure out, how int-to-string conversion exactly works. The Int32.ToString method calls an external method within the Number-class of the System namespace:
[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), SecuritySafeCritical]
public string ToString(IFormatProvider provider)
{
return Number.FormatInt32(this, null, NumberFormatInfo.GetInstance(provider));
}
The static Convert.ToString member does nothing else than calling ToString on the parameter:
[__DynamicallyInvokable]
public static string ToString(int value)
{
return value.ToString(CultureInfo.CurrentCulture);
}
Technically there would be no difference, if you'd write your own static member or extension, like you did in your question. So what's the difference between those two lines?
ints.ConvertAll<string>(i => i.ToString());
ints.ConvertAll(Convert.ToString);
Also - technically - there is no difference. The first example create's an anonymous method, that returns a string and accepts an integer. Using the integer's instance, it calls it's member ToString. The second one does the same, with the exception that the method is not anonymous, but an integrated member of the framework.
The only difference is that the second line is shorter and saves the compiler a few operations.
But why can't you call the non-static ToString directly?
Let's take a look into the ConvertAll-method of List:
public List<TOutput> ConvertAll<TOutput>(Converter<T, TOutput> converter)
{
if (converter == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter);
}
List<TOutput> list = new List<TOutput>(this._size);
for (int i = 0; i < this._size; i++)
{
list._items[i] = converter(this._items[i]);
}
list._size = this._size;
return list;
}
The list iteraterates over each item, calls the converter with the item as an argument and copys the result into a new list which it returns in the end.
So the only relation here is your converter that get's called explicitly. If you could pass Int32.ToString to the method, the compiler would have to decide to call this._items[i].ToString() within the loop. In this specific case it would work, but that's "too much intelligence" for the compiler. The type system does not support such code conversions. Instead the converter is an object, describing a method that can be called from the scope of the callee. Either this is an existing static method, like Convert.ToString, or an anonymous expression, like your lambda.
What causes the differences in your benchmark results?
That's hard to guess. I can imagine two factors:
Evaluating lambdas may result in runtime-overhead.
Framework calls may be optimized.
The last point especially means, that the JITer is able to inline the call which results in a better performance. However, those are just assumptions of mine. If anyone could clarify this, I'd appreciate it! :)
You hit the nail on the head yourself:
This works, but it creates an unnecessary anonymous method with the
lambda.
You can't do what you're asking for because there is no appropriate method group that you can use so the anonymous method is necessary. It works in that other case because the implicit range variable is passed to the delegate created by the method group. In your case, you need the method to be called on the range variable. It's a completely different scenario.

What is this "< >" behind a method means?

Like this:
var result1 = GetData<double>(someString);
var result2 = GetData<string>(someString);
What is this meant?
< >
How to return data?
public object GetData<Type>(string a)
{
// How do I know I should return this...
return 2.2;
// or this?
return "2.2";
}
What you're seeing here is called Generics. You can read about them in detail at the MSDN. In short, you can specify a Type Parameter along with your method. Based on the type, different code paths can be adopted. Read the link for examples and such.
In your particular case, the return type is independent of the type parameter. You are dealing with two different things. So, while returning, you can use any of those two statements.
return 2.2;
This will return a long 2.2. While the other statement will return a string which is "2.2". Since your return type is Object, both are acceptable. Though you haven't said that in problem, what you're looking for is something like this:
//Your generic GetData method
public TEntity GetData<TEntity>(string arg1)
{
var toReturn;
//Do some calculations
return (TEntity)toReturn;
}
Now, when you make a call like this:
var t = GetData<string>(string1);
variable t will hold a string. If you do a call like this:
var t = GetData<int>(string1);
variable t will hold and int.
This is a type parameter for generic method.
The term you're looking for is Generics. These are type arguments into the method, which mean that the method/class can work with specific types in a type-safe manner rather than falling back to everything being object (which also has a performance impact with boxing/unboxing).
From the C# guide:
Generics allow you to define type-safe data structures, without
committing to actual data types. This results in a significant
performance boost and higher quality code, because you get to reuse
data processing algorithms without duplicating type-specific code.
A few quick links:
.NET Generics in a Nutshell
An Introduction to C# Generics
That symbol after a method called Generic Method. It will defer the type inference during runtime.
Your GetData may be rewritten as below provided that you control the calling method as
GetData<float>("2.2")
GetData<string>("2.2")
public static T GetData<T>(string a)
{
return (T)Convert.ChangeType(a, typeof(T));
}

Get Constructor Matching Parameters

I have a method which takes in a constructor arguments as
Expression<func<T>>
thus declared as
object[] _constructorArgs = () => new MyClass("StringParam", 56, "ThirdParam");
I would instantiate this object as;
Activator.CreateInstance(typeof(MyClass), _constructorArgs);
Which works fine, but it's a bit slow.
Is there a way I can gather the types Constructor based on the contents of _constructorArgs so I would be able to call
ConstructorInfo.Invoke(_constructorArgs);
?
I know the Invoke is possible this way, it's just about finding the correct constructor based on the parameters in _constructorArgs.
Edit - For clarity
Apologies, I was very tired when I first asked this and should have given it more thought.
What I am doing is the following;
public object Create<T>(Expression<Func<T>> constructor)
{
//I didn't include this step in the original code
var constructorArguments =
(((NewExpression)constructor.Body).Arguments.Select(
argument => Expression.Lambda(argument).Compile().DynamicInvoke())).ToArray();
object[] _args = constructorArguments;
return Activator.CreateInstance(typeof(T), _args);
}
However, if I do the following instead;
ConstructorInfo c = type.GetConstructors().FirstOrDefault();
//Get the types constructor
return c.Invoke(_args);
I get better performance, I'm talking the first taking about 2800 milliseconds over a million iterations, using Invoke bringing that down to about 1000 milliseconds, thus 2.8 times faster.
This will work great if the first constructor always matches the arguments given, but this won't always be the case.
I want to know how I can get the correct ConstructorInfo based on arguments given.
If a million new objects per second isn't fast enough for you, you're going to have to go deeper. You need to start caching things. The simplest thing to cache is the constructor itself, so that you don't have to search for the correct constructor all the time. However...
Why are you doing this? Why don't you simply call the lambda outright? You've got all the code to instantiate the class, and then you throw it away and use Activator.CreateInstance? Why? Even if you do that, you don't need to search for the constructor - NewExpression.Constructor has the ConstructorInfo you need. Just do
((NewExpression)constructor.Body).Constructor.Invoke(_args)
and you're done, no searching needed. All the metadata is already there in the expression tree.
Please explain why you can't simply do return constructor(); (with caching if possible / needed - it's handy to pass things as lambda parameters, since you can then easily cache the method itself).
Activator.CreateInstance() under the hood calls GetConstructors() and iterates over them to find the matching ones. This would explain the difference in performance - and if you roll your own implementation chances are you will end up with the same or worse performance.
You could simplify the process by comparing types using parameterType.IsAssignableFrom(argType), and return the first match - you may end up using a different constructor than Activator.CreateInstance() though because it uses the best match, not the first match:
class DerivedClass : BaseClass { }
class Test
{
public Test(BaseClass c)
{
}
public Test(DerivedClass c)
{
}
}
// Uses the most specific constructor, Test(DerivedClass):
Activator.CreateInstance(typeof(Test), new DerivedClass());
Might be a bit late, but I found a nice implementation with caching, which claims to be 70 times faster thant Activator.CreateInstance;
this.Item = (T)Activator.CreateInstance(typeof(T), new Object[] { x, y }, null); // Classical approach
this.Item = Constructor<Func<int,int,T>>.Ctor(x,y); // Dynamic constructor approach
The complete implementation can be found here:
http://www.cyberforum.ru/blogs/32756/blog2078.html

an I prevent a specific type using generic restrictions

I have an overload method - the first implementation always returns a single object, the second implementation always returns an enumeration.
I'd like to make the methods generic and overloaded, and restrict the compiler from attempting to bind to the non-enumeration method when the generic type is enumerable...
class Cache
{
T GetOrAdd<T> (string cachekey, Func<T> fnGetItem)
where T : {is not IEnumerable}
{
}
T[] GetOrAdd<T> (string cachekey, Func<IEnumerable<T>> fnGetItem)
{
}
}
To be used with...
{
// The compile should choose the 1st overload
var customer = Cache.GetOrAdd("FirstCustomer", () => context.Customers.First());
// The compile should choose the 2nd overload
var customers = Cache.GetOrAdd("AllCustomers", () => context.Customers.ToArray());
}
Is this just plain bad code-smell that I'm infringing on here, or is it possible to disambiguate the above methods so that the compiler will always get the calling code right?
Up votes for anyone who can produce any answer other than "rename one of the methods".
Rename one of the methods. You'll notice that List<T> has an Add and and AddRange method; follow that pattern. Doing something to an item and doing something to a sequence of items are logically different tasks, so make the methods have different names.
This is a difficult use case to support because of how the C# compiler performs overload resolution and how it decides which method to bind to.
The first issue is that constraints are not part of the signature of a method and won't be considered for overload resolution.
The second problem you've got to overcome is that the compiler chooses the best match from the available signatures - which, when dealing with generics, generally means that SomeMethod<T>(T) will be considered a better match than SomeMethod<T>( IEnumerable<T> ) ... particularly when you've got parameters like T[] or List<T>.
But more fundamentally, you have to consider whether operating on a single value vs. a collection of values is really the same operation. If they are logically different, then you probably want to use different names just for clarity. Perhaps there are some use cases where you could argue that the semantic differences between single objects and collections of objects are not meaningful ... but in that case, why implement two different methods at all? It's unclear that method overloading is the best way to express the differences. Let's look at an example that lends to the confusion:
Cache.GetOrAdd("abc", () => context.Customers.Frobble() );
First, note that in the example above we are choosing to ignore the return parameter. Second, notice that we call some method Frobble() on the Customers collection. Now can you tell me which overload of GetOrAdd() will be called? Clearly without knowing the type that Frobble() returns it's not possible. Personally I believe that code whose semantics can't be readily inferred from the syntax should be avoided when possible. If we choose better names, this issue is alleviated:
Cache.Add( "abc", () => context.Customers.Frobble() );
Cache.AddRange( "xyz", () => context.Customers.Frobble() );
Ultimately, there are only three options to disambiguate the methods in your example:
Change the name of one of the methods.
Cast to IEnumerable<T> wherever you call the second overload.
Change the signature of one of the methods in a way that the compiler can differentiate.
Option 1 is self-evident, so I'll say no more about it.
Options 2 is also easy to understand:
var customers = Cache.GetOrAdd("All",
() => (IEnumerable<Customer>)context.Customers.ToArray());
Option 3 is more complicated. Let's look at ways we can be achieve it.
On approach is by changing the signature of the Func<> delegate, for instance:
T GetOrAdd<T> (string cachekey, Func<object,T> fnGetItem)
T[] GetOrAdd<T> (string cachekey, Func<IEnumerable<T>> fnGetItem)
// now we can do:
var customer = Cache.GetOrAdd("First", _ => context.Customers.First());
var customers = Cache.GetOrAdd("All", () => context.Customers.ToArray());
Personally, I find this option terribly ugly, unintuitive, and confusing. Introducing an unused parameter is terrible ... but, sadly it will work.
An alternative way of changing the signature (which is somewhat less terrible) is to make the return value an out parameter:
void GetOrAdd<T> (string cachekey, Func<object,T> fnGetItem, out T);
void GetOrAdd<T> (string cachekey, Func<IEnumerable<T>> fnGetItem, out T[])
// now we can write:
Customer customer;
Cache.GetOrAdd("First", _ => context.Customers.First(), out customer);
Customer[] customers;
var customers = Cache.GetOrAdd("All",
() => context.Customers.ToArray(), out customers);
But is this really better? It prevents us from using these methods as parameters of other method calls. It also makes the code less clear and less understandable, IMO.
A final alternative I'll present is to add another generic parameter to the methods which identifies the type of the return value:
T GetOrAdd<T> (string cachekey, Func<T> fnGetItem);
R[] GetOrAdd<T,R> (string cachekey, Func<IEnumerable<T>> fnGetItem);
// now we can do:
var customer = Cache.GetOrAdd("First", _ => context.Customers.First());
var customers = Cache.GetOrAdd<Customer,Customer>("All", () => context.Customers.ToArray());
So can use hints to help the compiler to choose an overload for us ... sure. But look at all of the extra work we have to do as the developer to get there (not to mention the introduced ugliness and opportunity for mistakes). Is it really worth the effort? Particularly when an easy and reliable technique (naming the methods differently) already exists to help us?
Use only one method and have it detect the IEnumerable<T> case dynamically rather than attempting the impossible via generic constraints. It would be "code smell" to have to deal with two different cache methods depending on if the object to store/retrieve is something enumerable or not. Also, just because it implements IEnumerable<T> does not mean it is necessarily a collection.
constraints don't support exclusion, which may seem frustrating at first, but is consistent and makes sense (consider, for example, that interfaces don't dictate what implementations can't do).
That being said, you could play around with the constraints of your IEnumerable overload...maybe change your method to have two generic typings <X, T> with a constraint like "where X : IEnumerable<T>" ?
ETA the following code sample:
void T[] GetOrAdd<X,T> (string cachekey, Func<X> fnGetItem)
where X : IEnumerable<T>
{
}

Categories