Pass instance method as a parameter without an instance - c#

I was wondering if, in C#, one could pass an instance method as a delegate without an instance. For reference, this is possible in Java by doing example(InstanceClass::InstanceMethod). The compiler then turns this into the equivalent of a Func<InstanceClass, ReturnType> which calls InstanceMethod() on the provided InstanceClass like so: item=>item.InstanceMethod(). Is this possible in C# and if it is, how would one do it?
Edit: To clarify, I am asking how I can pass the method in C# without using a lambda expression. The Lambda expression given is an example of what the compiler would turn the call into. Just passing the method instead of using a Lambda expression would be useful if the method had many arguments
Edit 2: Here is an example to illustrate my question. Java:
class Instance{
public void InstanceMethod(){System.out.println("Hello World");}
public static void Example(){
ArrayList<Instance> list = new ArrayList<>(5);
list.add(new Instance());
list.forEach(Instance::InstanceMethod)
}
}
Output: Hello World
C#:
public class Instance{
public void InstanceMethod(){Console.WriteLine("Hello World");}
public static void ForEach<T>(this IEnumerable<T> input, Action<T> action){
foreach(T item in input){
action(item);
}
}
public static void Example(){
List<Instance> list = new ArrayList<>(5);
list.Add(new Instance());
list.ForEach(Instance.InstanceMethod);//error need instance to call method
}

Even in Java you are still dealing with an instance, but Java's syntactic sugar hides that.
There is no equivalent for your case. You have to do
public static void Example()
{
var list = new List<Instance>(5);
list.Add(new Instance());
list.ForEach(x => x.InstanceMethod());
}
or addstatic toInstanceMethod (since that method has no state):
public static void InstanceMethod()
{
Console.WriteLine("Hello World");
}
public static void Example()
{
var list = new List<Instance>(5);
list.Add(new Instance());
list.ForEach(x => InstanceMethod());
}
If your InstanceMethod accepted an Instance as a parameter and Example wasn't static, there is some C# syntactic sugar called a method group that would work:
public void InstanceMethod(Instance x)
{
Console.WriteLine("Hello World");
}
public void Example()
{
var list = new List<Instance>(5);
list.Add(new Instance());
list.ForEach(InstanceMethod);
}
Of all of the above, the first one is idiomatic C# and the one I would pick. It's probably the most readable and expected for C# programmers to read.

Related

How could I achieve JQuery style method calls on IEnumerables in C#?

In JQuery you can write $('.my-class').hide() and it will call hide() on all the results. There's no for loop, no iterating, no LINQ extensions and lambdas etc. and it makes dealing with lists super fun. I want to be able to have this functionality on IEnumerables in C#. I think Matlab has a similarly concise syntax when operating on arrays/matrices.
Long story short, I want the following code (or similar) to work:
class Program
{
static List<MyClass> MyList = new List<MyClass>();
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
MyList.Add(new MyClass());
MyList.MyMethod();
// should be exactly equivalent to:
MyList.Select(n => n.MyMethod());
}
}
class MyClass
{
public int MyMethod() { return 123; }
}
I'm aware this is possible on a case-by-case basis using extension methods:
public static IEnumerable<int> MyMethod(this IEnumerable<MyClass> lst)
{
return lst.Select(n => n.MyMethod());
}
But we'd have to create one extension method for every single method on every single type that you wanted this behaviour on.
Ideally this would be possible for all types and all methods and still be type-safe at compile time. I suspect I'm asking too much from the C# language here, but how would we do this or something similar in a as-generic-as-possible way?
Possible solutions:
Auto-generate extension methods for particular types. If we only intend to use this notation for a few types, we could just generate the extension methods once automatically. This would achieve the exact syntax and full type safety but generating code would be a pain.
A single extension method that returns a dynamic object built using reflection on the supplied type. The idea is that we'd use reflection to iterate through the type's methods and build up a dynamic object that would have all the methods like .MyMethod() that would behind the scenes call Select(...) on the IEnumerable. The syntax would end up being something like MyList.Selector().MyMethod(). But now we've lost the syntax and type safety. Clever, maybe. Useful, probably not.
Intercepting method calls? Is it possible to decide how to react to a method call at runtime? I don't know. Again you'd lose type safety.
The most simple solution is using dynamic objects. If you are willing to throw away type safety, you can make a IEnumerable type that behaves statically when needed and dynamically otherwise, here's a sample prototype:
public class DynamicIEnumerable<T> : DynamicObject, IEnumerable<T>
{
public IEnumerable<T> _enumerable;
public DynamicIEnumerable(IEnumerable<T> enumerable)
{
this._enumerable = enumerable;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
result = new DynamicIEnumerable<T>(_enumerable.Select(x => (T)typeof(T).InvokeMember(binder.Name, BindingFlags.InvokeMethod, null, x, null)));
return true;
}
public IEnumerator<T> GetEnumerator()
{
return _enumerable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _enumerable.GetEnumerator();
}
}
In TryInvokeMember, the invoked member on IENumerable is applied on all items using reflection. The only constraints on this approach is that you have to return this in invoked method. Here's a sample of how to use this approach:
public class SomeClass
{
public int Value {get;set;}
public SomeClass(int value)
{
this.Value = x;
}
public SomeClass Plus10()
{
Value += 10;
return this;
}
}
static void Main()
{
dynamic d = new DynamicIEnumerable<X>(Enumerable.Range(0, 10).Select(x => new SomeClass(x)));
foreach (var res in d.Plus10().Plus10())
Console.WriteLine(res.Value);
}
how would we do this or something similar in a as-generic-as-possible way?
This isn't a pretty solution but it does work:
public class MyClass
{
public void MyMethod()
{
}
public void MyMethod2()
{
}
}
Extension Method:
public static class WeirdExtensions
{
public static IEnumerable<T> CallOnAll<T>(this IEnumerable<T> instance ,
Action<T> call)
{
foreach(var item in instance)
{
call(item);
}
return instance;
}
}
Usage (chaining/fluent):
var blah = new List<MyClass>();
blah.CallOnAll(b => b.MyMethod())
.CallOnAll(b => b.MyMethod2());
Notes
This isn't quite possible due to a the underlying assumption that you'd have to every single method on every single type. In jQuery/Html there is only one underlying type of an Html Element. All elements are exposed to the same methods (whether or not the type supports it). In jQuery, you can call $('head').hide() but it won't do anything visually, but because it is an element, it will be inline styled. If you need a new method, you do have a build one, but for only one type because there is only one type.
In contrast with C# you build your types (many many types) and they all have different methods (sure there could be overlap).

C# extension method for a method group

I want to implement an extension method for a method. Consider the following code sample (http://dotnetfiddle.net/HztiOo) :
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
A a = new A();
// Noticed that Next() is called twice
Console.WriteLine(a.Next(1));
Console.WriteLine(a.Next(1));
// Works
var withCache = ((Func<int,int>)a.Next).AddCaching();
withCache = new Func<int,int>(a.Next).AddCaching();
withCache = ExtensionMethods.AddCaching<int,int>(a.Next);
// Doesn't work :(
// withCache = a.Next.AddCaching<int,int>();
// Func<int,int> withCache = a.Next.AddCaching();
// Notice that Next() is only called once
Console.WriteLine(withCache(1));
Console.WriteLine(withCache(1));
}
}
public class A
{
public int Next(int n)
{
Console.WriteLine("Called Next("+n+")");
return n + 1;
}
}
public static class ExtensionMethods
{
public static Func<TKey,TVal> AddCaching<TKey,TVal>(this Func<TKey,TVal> fetcher)
{
var cache = new Dictionary<TKey, TVal>();
return k =>
{
if (!cache.ContainsKey(k)) cache[k] = fetcher(k);
return cache[k];
};
}
}
I would like to be able to call the extension method without an explicit cast. In both "doesn't work" examples above, the type system should be able to figure out which overload to use on its own...
Why can't I just use a.Next.AddCaching<int,int>() ?
Note: this is just an example, I am not interested in discussing the best way to add a cache to a method invocation, as there are many other possibilities for this kind of extensions.
According to Eric Lippert blog method group is typeless expression. And you can't do anything, just deal with it.
That's exact reason why you can't implicitly cast it to specific delegate and add extension method to it
You can achieve something stylistically similar to what you are looking for by exposing you method as a Func, as follows (https://dotnetfiddle.net/BTyJdU). Obviously this involves modifying the class, so it can't be achieved with an extension method only.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
A a = new A();
// Noticed that Next() is called twice
Console.WriteLine(a.Next(1));
Console.WriteLine(a.Next(1));
// Works now :)
var withCache = a.Next.AddCaching<int,int>();
withCache = a.Next.AddCaching();
// Notice that Next() is only called once
Console.WriteLine(withCache(1));
Console.WriteLine(withCache(1));
}
}
public class A
{
public Func<int,int> Next;
public A()
{
Next = NextInternal;
}
private int NextInternal(int n)
{
Console.WriteLine("Called Next("+n+")");
return n + 1;
}
}
public static class ExtensionMethods
{
public static Func<TKey,TVal> AddCaching<TKey,TVal>(this Func<TKey,TVal> fetcher)
{
var cache = new Dictionary<TKey, TVal>();
return k =>
{
if (!cache.ContainsKey(k)) cache[k] = fetcher(k);
return cache[k];
};
}
}
I've also put together a fiddle which uses extension methods only. It involves calling an extension on the object rather than the method: https://dotnetfiddle.net/XaLndp
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
A a = new A();
// Noticed that Next() is called twice
Console.WriteLine(a.Next(1));
Console.WriteLine(a.Next(1));
// An alternative, that uses extension methods only
var withCache = a.AddCaching<A,int,int>(x => x.Next);
// Notice that Next() is only called once
Console.WriteLine(withCache(1));
Console.WriteLine(withCache(1));
}
}
public class A
{
public int Next(int n)
{
Console.WriteLine("Called Next("+n+")");
return n + 1;
}
}
public static class ExtensionMethods
{
public static Func<TKey,TVal> AddCaching<T,TKey,TVal>(this T wrapped, Func<T,Func<TKey,TVal>> fetcher)
{
var cache = new Dictionary<TKey, TVal>();
return k =>
{
if (!cache.ContainsKey(k)) cache[k] = fetcher(wrapped)(k);
return cache[k];
};
}
}
You are able to write extension methods for delegates. In your example:
Why can't I just use a.Next.AddCaching() ?
In that question, a.Next isn't a type. Extension methods only work for types. Think about it. In your AddCaching extension method, what would you write after this? You need a type. In this case, you used the delegate Func<TKey,TVal>. That means it'll extend that delegate. For you example to compile, you need to write:
((Func<int,int>)a.Next).AddCaching<int,int>()
This will compile properly. Additionally, since you are defining the generic types in the delegate, you can actually call it like this:
((Func<int,int>)a.Next).AddCaching()
It'll know it is using <int,int> from the delegate.
So, you were close, you just needed to cast a.Next to a type, the delegate Func<int,int> for it to compile. It is the same rules that apply to extending any other type in the language.

Can a multicast delegate in C# 4.0 be created from some sort of collection of method names?

I'm writing a simple game in XNA and I've faced a problem with delegates. I use them to represent physics in the game, e.g.:
public delegate void PhysicsLaw(World world);
//for gravitation
static public void BallLawForGravity(World world)
{
if (world.ball.position.Y != world.zeroLevel)
//v(t) = v0 + sqrt(c * (h - zeroLevel))
world.ball.speed.Y += (float)Math.Sqrt(0.019 * (world.zeroLevel - world.ball.position.Y));
}
And I want to create multicast delegates for different objects/circumstances consisting from many methods such as BallLawForGravity(), but I can do it only like this:
processingList = BallLawForBounce;
processingList += BallLawForAirFriction;
...
processingList += BallLawForGravity;
Obviously, it doesn't look good. Is there any standard way to create a multicast delegate from collection of method names?
Use the static method Delegate.Combine Method (Delegate[]) for such tasks.
PhysicsLaw[] delegates = new PhysicsLaw[] {
new PhysicsLaw( PhysicsLaw ),
new PhysicsLaw( BallLawForAirFriction )
};
PhysicsLaw chained = (PhysicsLaw) Delegate.Combine( delegates );
chained(world);
More examples.
Update
You can use the creating delegate via Reflection for this but I don't recommend it, because it's very slow technic.
Let's say you've declared
public delegate void foo(int x);
public static void foo1(int x) { }
public static void foo2(int x) { }
public static void foo3(int x) { }
Now you can combine them directly with Delegate.Combine if you don't mind typing the delegate name twice:
foo multicast = (foo)Delegate.Combine(new foo[] { foo1, foo2, foo3 });
Or you can write a generic function to combine them if you don't mind typing the delegate name once:
public static T Combine<T>(params T[] del) where T : class
{
return (T)(object)Delegate.Combine((Delegate[])(object[])del);
}
foo multicast2 = Combine<foo>(foo1, foo2, foo3);
Or you can write a non-generic function to combine them if you don't want to type the delegate name at all:
public static foo Combine(params foo[] del)
{
return (foo)Delegate.Combine(del);
}
foo multicast3 = Combine(foo1, foo2, foo3);

C# Generic overloading of List<T> : How would this be done?

The StringBuilder class allows you, in what I consider to be a very intuitive way, to chain method calls to .Append(), .AppendFormat() and some others like so:
StringBuilder sb = new StringBuilder();
sb.Append("first string")
.Append("second string);
The List class' .Add() method, on the other hand, returns void - so chaining calls doesn't work. This, in my opinion and the immortal words of Jayne Cobb "just don' make no kinda sense".
I admit that my understanding of Generics is very basic, but I would like to overload the .Add() method (and others) so that they return the original object, and allow chaining. Any and all assistance will be rewarded with further Firefly quotes.
If you want to keep the same name for the Add method, you could hide the method from the base class:
public class MyList<T> : List<T>
{
public new MyList<T> Add(T item)
{
base.Add(item);
return this;
}
}
However, this will only work if you're manipulating the list with a variable explicitly typed as MyList<T> (i.e. it won't work if your variable is declared as IList<T> for instance). So I think the solutions involving an extension method are better, even if that means changing the name of the method.
Although others have already posted solutions with extension methods, here's another one, that has the advantage of conserving the actual type of the collection:
public static class ExtensionMethods
{
public static TCollection Append<TCollection, TItem>(this TCollection collection, TItem item)
where TCollection : ICollection<TItem>
{
collection.Add(item);
return collection;
}
}
Use it like that:
var list = new List<string>();
list.Append("Hello").Append("World");
use can create extension method
public static class ListExtensions
{
public static List<T> AddItem<T>(this List<T> self, T item)
{
self.Add(item);
return self;
}
}
var l = new List<int>();
l.AddItem(1).AddItem(2);
EDIT
we can also make this method generic over collection parameter
public static class ListExtensions
{
public static TC AddItem<TC, T>(this TC self, T item)
where TC : ICollection<T>
{
self.Add(item);
return self;
}
}
var c1 = new Collection<int>();
c1.AddItem(1).AddItem(2);
var c2 = new List<int>();
c2.AddItem(10).AddItem(20);
EDIT 2:
Maybe someone will find this trick useful, it is possible to utilize nested object initializer and collection initializer for setting properties and adding values into existing instances.
using System;
using System.Collections.Generic;
using System.Linq;
struct I<T>
{
public readonly T V;
public I(T v)
{
V = v;
}
}
class Obj
{
public int A { get; set; }
public string B { get; set; }
public override string ToString()
{
return string.Format("A={0}, B={1}", A, B);
}
}
class Program
{
static void Main()
{
var list = new List<int> { 100 };
new I<List<int>>(list)
{
V = { 1, 2, 3, 4, 5, 6 }
};
Console.WriteLine(string.Join(" ", list.Select(x => x.ToString()).ToArray())); // 100 1 2 3 4 5 6
var obj = new Obj { A = 10, B = "!!!" };
Console.WriteLine(obj); // A=10, B=!!!
new I<Obj>(obj)
{
V = { B = "Changed!" }
};
Console.WriteLine(obj); // A=10, B=Changed!
}
}
public static IList<T> Anything-not-Add*<T>(this IList<T> list, T item)
{
list.Add(item);
return list;
}
* AddItem, Append, AppendList, etc. (see comments below)
The same idea came to my mind like other guys' too, independently:
public static TList Anything<TList, TItem>(this TList list, TItem item)
where TList : IList<TItem>
{
list.Add(item);
return list;
}
And Thomas is right: as far as IList<T> inherits ICollection<T> you should use ICollection.
Have an extension method off:
public static List<T> Append(this List<T> list, T item)
{
list.Add(item);
return self;
}
Note that we have to create it with a new name, as if an instance member matches the signature (the 'Add' you are already complaining about) then the extension method won't be called.
In all though, I'd recommend against this. While I like chaining myself, it's being rare in C# libraries means it's not as idiomatic as it is in other languages where it's more common (no technical reason for this, though some differences in how properties work encourages it a bit more in some other languages, just the way things are in terms of what is common). Because of this, the constructs it enables aren't as familiar in C# as elsewhere, and your code is more likely to be misread by another dev.
You could use an extension method with a different name:
public static T Put<T, U>(this T collection, U item) where T : ICollection<U> {
collection.Add(item);
return collection;
}
To create code like this:
var list = new List<int>();
list.Put(1).Put(2).Put(3);
To retain the name Add, however, you can have a method like this:
public static T Add<T, U>(this T collection, Func<U> itemProducer)
where T : ICollection<U> {
collection.Add(itemProducer());
return collection;
}
And create code like this:
list.Add(()=>1).Add(()=>2).Add(()=>3);
It doesn't look that good though.
Maybe if we change the type we can have a better syntax.
Given this class:
public class ListBuilder<T> {
IList<T> _list;
public ListBuilder(IList<T> list) {
_list = list;
}
public ListBuilder<T> Add(T item) {
_list.Add(item);
return this;
}
}
You can have this method:
public static ListBuilder<T> Edit<T>(this IList<T> list) {
return new ListBuilder<T>(list);
}
And use code like this:
list.Edit().Add(1).Add(2).Add(3);
I'm sure you won't appreciate this answer but there's a very good reason that List<>.Add() works this way. It is very fast, it needs to be to be competitive with an array and because it is such a low-level method. It is however just a hair too big to get inlined by the JIT optimizer. It cannot optimize the return statement you'd need to return the list reference.
Writing lst.Add(obj) in your code is for free, the lst reference is available in a CPU register.
A version of Add() that returns the reference makes the code almost 5% slower. It's a lot worse for the proposed extension method, there an entire extra stack frame involved.
I like the extension approach that others have mentioned as that seems to answer the question well (although you would have to give it a different method signature than the existing Add()). Also, it does seem like there's some inconsistency about object returns on calls like this (I thought it was a mutability issue, but the stringbuilder is mutable isn't it?), so you raise an interesting question.
I'm curious, though, if the AddRange method would not work as an out-of-the-box solution? Is there a particular reason you want to chain the commands instead of passing everything in as a an array?
Would do something like this not accomplish what you need?
List<string> list = new List<string>();
list.AddRange(new string[]{
"first string",
"second string",
});

Overloading methods in C# .NET

A variable of the type Int32 won't be threated as Int32 if we cast it to "Object" before passing to the overloaded methods below:
public static void MethodName(int a)
{
Console.WriteLine("int");
}
public static void MethodName(object a)
{
Console.ReadLine();
}
To handle it as an Int32 even if it is cast to "Object" can be achieved through reflection:
public static void MethodName(object a)
{
if(a.GetType() == typeof(int))
{
Console.WriteLine("int");
}
else
{
Console.ReadLine();
}
}
Is there another way to do that? Maybe using Generics?
Runtime overload resolution will not be available until C# 4.0, which has dynamic:
public class Bar
{
public void Foo(int x)
{
Console.WriteLine("int");
}
public void Foo(string x)
{
Console.WriteLine("string");
}
public void Foo(object x)
{
Console.WriteLine("dunno");
}
public void DynamicFoo(object x)
{
((dynamic)this).Foo(x);
}
}
object a = 5;
object b = "hi";
object c = 2.1;
Bar bar = new Bar();
bar.DynamicFoo(a);
bar.DynamicFoo(b);
bar.DynamicFoo(c);
Casting this to dynamic enables the dynamic overloading support, so the DynamicFoo wrapper method is able to call the best fitting Foo overload based on the runtime type of the argument.
public static void MethodName(object a)
{
if(a is int)
{
Console.WriteLine("int");
}
else
{
Console.WriteLine("object");
}
}
No, the specific overload of a method that is called is determined at compile-time, not at runtime, unless you're using reflection, thus if you've cast your int to an object, the object overload will be called. I don't believe there's any other way to do this, and generics won't do it for you either.
would this not work?
void MethodName<T>(object a){
T item = a as T;
// treat in the manner you require
}
MethodName<object>(1);
MethodName<Int32>(1);
Perhaps:
public static void MethodName(Type t)
{
Console.WriteLine(t.Name);
}
Then call it:
int a = 0;
string b = "";
object c = new object();
MethodName(a.GetType());
MethodName(b.GetType());
MethodName(c.GetType());
Or:
public static void MethodName<T>(T a)
{
Console.WriteLine(a.GetType().Name);
}
And finally:
public static void MethodName<T>()
{
Console.WriteLine(typeof(T).Name);
}
Update:
It comes down to the fact that the language must somehow be able to determine what type you will be dealing at compile time.
You're pretty much stuck with if/else constructs if you're looking to switch on types. The switch statement itself won't work due to polymorphism. If you're using non-primitive objects, than you can usually accomplish this sort of behavior either with polymorphism or interfaces, such that:
public static void MethodName(MyBaseObject obj)
{
Console.WriteLine(obj.MyVirtualFunctionCall());
}
dynamic overloading was an issue until .NET 3.5, but with .NET 4 its very feasible with few lines of code.
public void publish(dynamic queue)
{
publish(queue);
Console.WriteLine("dynamic queue publishing");
}
public void publish(ValidationQueue queue)
{
Console.WriteLine("Validation queue publishing");
}
how to call
foreach (var queue in _vodaQueueDAO.FetchAllReadyQueuesWithHighestPriority())
{
PublishingService.publish(queue);
}
I wrote an implementation for .NET 3.5 where you e.g. can do something like:
object a = 5;
OverloadResolver.Invoke(MethodName, a);
and it would use the int overload.
Works with compiled and cached Lambda expressions so the performance should be ok.
If anybody needs it, mail me, herzmeisterderwelten, who resides at gmail.com

Categories

Resources