The following test passes, but I'm wondering if a unified treatment is possible. Can it be done?
public abstract class MyInvokable<TResult> {
public abstract TResult Invoke();
}
public class IntInvokable: MyInvokable<int> {
public override int Invoke() {
return 12;
}
}
[Test()]
public void FunctionInvokeTest () {
Func<int> foo = () => 6;
IntInvokable bar = new IntInvokable();
int six = foo.Invoke();
int twelve = bar.Invoke();
Assert.AreEqual(6, six);
Assert.AreEqual(12, twelve);
/* Now, what I really want to do but can't, as far as I can tell:
List<SomeType> list = new List<SomeType>(){foo, bar};
Assert.AreEqual(6, list[0].Invoke());
Assert.AreEqual(12, list[1].Invoke()); */
}
EDIT: started a feature request with Microsoft here:
http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/10185579-create-an-iinvokable-t-interface
C# does not allow anything even remotely close to this type of dynamic behaviour.
But, it you do need to go this route, you can always use dynamic, basically signaling the compiler that all bets are off. This would work:
List<dynamic> list = new List<dynamic>(){foo, bar};
Assert.AreEqual(6, list[0].Invoke());
Assert.AreEqual(12, list[1].Invoke());
but you cannot guarantee in any way that whatever is in the list variable, actually has an Invoke method.
The feature most like this one is TypeScript's structural interfaces - as long as a type has all the methods / properties required by the interface, it's considered to implement the interface.
In C#, the only way that two different things can be considered as having a similar type, is for them to explicitly declare that they implement the same interface, or inherit the same base class.
It would be nice to be able to somehow have a structural semantics in C#, but it's not even on the roadmap, AFAIK.
To have a List<T> where the only requirement you want is that T has a parameterless Invoke method you need to bake that requirement into either an interface or a base class.
So either of these two would work:
public interface IInvokable
{
int Invoke();
}
var l = new List<IInvokable>();
or this:
public class Invokable
{
public virtual int Invoke() { ... }
}
var l = new List<Invokable>();
Obviously, now you need to wrap the delegate in that class, for instance like this:
public class FuncInvokable : IInvokable
{
private readonly Func<int> _Func;
public FuncInvokable(Func<int> func) { _Func = func; }
public int Invoke() { return _Func(); }
}
or... you could just place delegates into the list and wrap all objects in delegates instead:
var l = new List<Func<int>>();
l.Add(foo);
l.Add(() => bar.Invoke());
but there is no way to define this:
var l = new List<Type that has an Invoke method>();
Related
I have various interfaces and I need to be able to call them. Here is the base class:
public class MyActorBase<TChild>: ActorBase where TChild : MyActorBase<TChild>
{
public MyActorBase()
{
var actors = ChildClass
.GetInterfaces()
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IActorMessageHandler<>))
.Select(x=> (arguments: x.GetGenericArguments(), definition: x))
.ToImmutableList();
if (actors.Any())
{
var ty = actors.First();
var obj = Activator.CreateInstance(ty.definition, true);
// how to call method implementation
}
}
protected sealed override bool Receive(object message) => false;
private Type ChildClass => ((this as TChild)?? new object()).GetType();
}
public interface IActorMessageHandler<in T>
{
Task Handle(T msg);
}
I read these blog post:
Dont use Activator.CreateInstance
Linq Expressions
Creating objects performance implications
The writers already knew the type at compile time hence were able to cast correctly. I do not know anything at compile time so I cannot use a generic method or typecast it using () operator or as operator.
UPDATE: I think people are not getting the idea of what I want to achieve. so consider this. I made a nuget package which anyone can
depend upon. Somewhere in the world, someone writes this code:
public class MyMessage
{
public int Number { get; }
public MyMessage(int number) => Number = number;
}
public class MyNewActor: MyActorBase<MyNewActor>, IActorMessageHandler<MyMessage>
{
public Task Handle(MyMessage msg)
{
return Task.CompletedTask;
}
}
I want that any class that implements the IActorMessageHandler, i should be able to call its method Handle(T msg). so while I was able to instantiate it (considering that I'm not using any dependency injection) how can I call the method in the most efficient way?
Is there any alternate to reflection?
you should not use Activator.CreateInstance it's very much expensive. instead, you may use Expression.Lamda to create objects in an efficient way.
var object = Expression.Lambda<Func<IActorMessageHandler<TChild>>>(Expression.New(ty.definition.Value.GetConstructor(Type.EmptyTypes) ?? throw new
Exception("Failed to create object"))
).Compile()();
What about using the dynamic keyword? This is basically optimized reflection nicely wrapped for you:
dynamic obj = Activator.CreateInstance(ty.definition, true);
Task t = obj.Handle(msg); //need to define msg before
It bypasses compile-time checks and defers method look-up at run-time.
Note that it will fail at run-time if no resolution for the Handle method can be performed.
This blog post concludes that dynamic ends up being much quicker than reflection when called fairly often because of caching optimizations.
I'm learning about C# extension methods at the moment. I have read in a couple of places that adding members to classes reduces backwards compatibility for code that uses those classes.
I've read this here:
https://blogs.msdn.microsoft.com/vbteam/2007/03/10/extension-methods-best-practices-extension-methods-part-6/
And page 418 of Troelson's Pro C# book.
I'm afraid this doesn't make sense to me. Surely any code that uses instances of those classes as they WERE before extra members were added (without using extension methods, just by adding them to the class), will still be able to call all the old methods, properties, fields and constructors just like before, as they haven't changed. Even if the new members can change the state of the object, they will never be called in the old code, so therefore the code is backwards compatible.
What am I not seeing here?
Here's one possible way adding a new method could actually break client code...
void Main()
{
var oldFoo = new OldFoo();
var oldResult = oldFoo.Calculate(2, 2); // 4
var newFoo = new NewFoo();
var newResult = newFoo.Calculate(2, 2); // 0
}
public class OldFoo
{
public int Calculate(params int[] values)
{
return values.Sum();
}
}
public class NewFoo
{
public int Calculate(params int[] values)
{
return values.Sum();
}
public int Calculate(int value1, int value2)
{
return value1 - value2;
}
}
And here's another way, specifically dealing with an extension method...
Initially, the client defines an extension method to give Foo the ability to Combine:
void Main()
{
var foo = new Foo();
var result = foo.Combine(2, 2); // "22"
}
public static class Extensions // added by client
{
public static string Combine(this Foo foo, params int[] values)
{
return string.Join(string.Empty, values.Select(x => x.ToString()));
}
}
public class Foo { }
Later, the developer of Foo adds a new Combine method to the class:
void Main()
{
var foo = new Foo();
var result = foo.Combine(2, 2); // 4
}
public static class Extensions
{
public static string Combine(this Foo foo, params int[] values)
{
return string.Join(string.Empty, values.Select(x => x.ToString()));
}
}
public class Foo
{
public int Combine(params int[] values)
{
return values.Sum();
}
}
Note that the extension method gets effectively blocked or shadowed by the new Combine instance method.
The point is that extension methods may share the same namespace with member methods and if they do, member methods take precedence sheerly by name. The implication of this is that you, as a library developer, may break code of a client who introduced an extension method to your class in his own application. Without you being able to know that you are doing it.
If you update your library class with a new member method and your client installs the update, he may find your new method has the same name as the extension method he added earlier. Or he may not find it if the argument lists are compatible. His extension method will now be hidden by your new member method. His code will now either not compile (incompatible argument list), or, worse, behave differently.
A real world analogy might help. Think about it like machinery. Imagine someone designs an engine that people start using as a basis for some equipment, say a harvester. If the engine designer decides a fuel filter would be helpful and adds that in, it could ruin the harvester design because that design may have put something in the space now occupied by the new fuel filter.
Adding the new member (the fuel pump) decreased the backwards compatibility. The harvester design was based on a version backward in history.
And a more programming based example: A app designer creates a parser for his application that behaves in a particular way. After release, it's discovered that the parser does not implement the spec correctly for some uncommon conditions. A new version is released that correctly implements the spec but adds a flag to provide the previous behavior.
I have an Address class:
public class Address
{
//Some stuff
}
and there's a corresponding *Wrapper class to enforce certain rules on how to
use the Address class:
public class AddressWrapper : IWrapped<Address>
{
private Address _wrapped;
public Address GetWrapped()
{
return _wrapped;
}
//And some more
}
where IWrapped is defined as:
public interface IWrapped<T>
{
T GetWrapped();
}
I have the following generic class for saving these entities (there are other
entities that follow this pattern of Entity and EntityWrapper):
public class GenericRepository
{
private GenericRepository() { }
public static void Add<T>(IWrapped<T> entity)
{
//Do something
}
public static void AddList<T>(IList<IWrapped<T>> entities)
{
//Do something
}
}
and I have this test code:
[Test]
public void UseGenericRepository()
{
AddressWrapper addrW = new AddressWrapper();
addrW.AddrLine1 = "x";
addrW.AddrLine2 = "y";
addrW.AddrLine3 = "z";
addrW.City = "Starling City";
//This works as expected
GenericRepository.Add<Address>(addrW);
IList<AddressWrapper> addrList = new List<AddressWrapper>();
//Fill up the addrList
//This gives error: best overloaded method match has some invalid
//arguments
GenericRepository.AddList<Address>(addrList);
}
AddressWrapped is of type IWrapped<Address> (i.e., it implements it) and
Address is the type parameter being given to the AddList method, so the
types should line up. I know that this is due to my limited knowledge of C#
generics (familiar with Java generics), but can't figure out what's wrong here
--- it should work.
This probably doesn't make any difference, but here's my config:
NHibernate 4.x
.NET Framework (4.5)
This is because of the missing type variance of IList<T>. (IList<int> is not an IList<object>).
Use IEnumerable<T>, because it is covariant:
public static void AddList<T>(IEnumerable<IWrapped<T>> entities)
{
//Do something
}
Reason: If you get an instance of List<AddressWrapper>, the compiler doesn't know if it is compatible with any possible implementation of IList<IWrapped<T>>. Assume another class that implements IWrapped<T>. It wouldn't be compatible when writing to the List. Even though you don't write to the list in AddList, the compiler only accepts compatible types. IEnumerable<T> cannot be written, so it can be variant.
Not related to the question I suggest to use covariance for your own interface as well:
public interface IWrapped<out T>
to make IWrapped<Thing> compatible with IWrapped<SpecificThing>.
MSDN: https://msdn.microsoft.com/en-us/library/ee207183.aspx
To make this clear by an example. Would would you expect happen if we had two types implement IWrapped<T>?
public class AddressWrapper : IWrapped<Address>
{
private Address _wrapped;
public Address GetWrapped()
{
return _wrapped;
}
//And some more
}
public class OtherWrapper : IWrapped<MailBox>
{
public MailBox GetWrapped()
{
throw new MailBox();
}
}
And we tried to add them to a third list inside AddList<T>:
public static void AddList<T>(IList<IWrapped<T>> entities)
{
internalList = new List<IWrapped<T>>();
list.AddRange(entities); // BOOM.
}
The type system is keeping you from making a mistake. List<T> isn't covariant exactly for that reason.
At the point at which you're trying to call AddList(), for all the compiler knows, that method may add objects of any type that implements IWrapper<Address> (i.e. types that aren't AddressWrapper) to the passed in list.
That would be bad because the list you're trying to pass to the method doesn't want to contain anything other than AddressWrappers.
NB: Please see the answer by #StefanSteinegger, it is especially enlightening.
What worked for me was changing the way I was defining addrList, from:
IList<AddressWrapper> addrList = new List<AddressWrapper>();
to:
IList<IWrapped<Address>> addrList = new List<IWrapped<Address>>();
However, I am also changing the signature of the GenericRepository.AddList<T>(..) method to take an IEnumerable as that also helps indicate that the input is read-only. So:
public static void AddList<T>(IEnumerable<IWrapped<T>> entities)
{
//Do some stuff
}
I have just familiarized myself a little bit with C# delegates. One can subscribe multiple delegate instances to a delegate by the "+=" operator. But is it also possible to have a controller class that has delegates for all the methods in second class, and have the methods being added automatically, i.e. without having to add (or even know) each method individually to the corrsponding delegate ?
In simplified code (omitting access modifiers etc.):
class Car
{
void Start();
void Drive();
}
// I would like to have the following class generated automatically
// without needing to repeat all the methods of Car, i.e.
// without declaring a delegate instance for each of them
class CarController
{
delegate void DoSomething();
DoSomething StartAll;
DoSomething DriveAll;
void Subscribe(Car anotherCar)
{
StartAll += anotherCar.Start;
DriveAll += anotherCar.Drive;
}
}
EDIT:
Rawling's solution is the one that I like best. It's simple and clear. As a little tweak I have tried how the thing would work with dynamically typed objects, and it works indeed: complete decoupling between Controller and controlled objects. Of course such usage of "dynamic" is not of everyone's taste...
public class CallAller2 : HashSet<dynamic>
{
public void CallAll(Action<dynamic> action)
{
foreach (dynamic t in this)
{
try {action(t);} catch (RuntimeBinderException) {};
}
}
}
class Bike
{
void Drive();
}
CallAller2 ca = new CallAller2();
ca.Add(new Car());
ca.Add(new Bike());
ca.CallAll(c => c.Start()); // is ignored by Bike which does not implement it
ca.CallAll(c => c.Drive());
Now I realise this is just essentially recreating the much-maligned List<T>.ForEach. Why not just use that, since it's there?
Although it doesn't give you the ability to just call .StartAll or .DriveAll, you could do something as simple as
class CallAller<T> : HashSet<T>
{
public void CallAll(Action<T> action)
{
foreach (T t in this)
{
action(t);
}
}
}
var ca = new CallAller<Car>();
ca.Add(myFirstCar);
ca.Add(mySecondCar);
// Call a simple function
ca.CallAll(c => c.Start());
// Call a function taking parameters
ca.CallAll(c => c.SetRadio(88.1, RadioType.FM));
// Get return values... if you really need to.
Dictionary<Car, int> returnValues = new Dictionary<Car, int>();
ca.CallAll(c => returnValues.Add(c, c.GetNumberOfTyres()));
If you want something with actual methods to call and Intellisense, you'll need to look into code generation - it's possible, but I doubt it'd be worth the hassle.
I think this should work:
//Edit: Don't simplify the MethodInfo mi1 = mi, otherwise you get a problem called Access to modified closure
static IList<Action> getDelegatesFromObject(Object obj)
{
Type type = obj.GetType();
List<Action> Actions = new List<Action>();
foreach (MethodInfo mi in type.GetMethods())
{
MethodInfo mi1 = mi;
Actions.Add(
() => mi1.Invoke(obj, new object[] {})
);
}
return Actions;
}
Is it possible to add a generic delegate Action to a List collection?
I need some kind of simple messaging system for a Silverlight application.
UPDATE
The following is what i realy "want"
class SomeClass<T>
{
public T Data { get; set; }
// and more ....
}
class App
{
List<Action<SomeClass<T>>> _actions = new List<Action<SomeClass<T>>>();
void Add<T>( Action<SomeClass<T>> foo )
{
_actions.Add( foo );
}
}
Compiler:
The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)
initial code snipped
class SomeClassBase
{ }
class SomeClass<T> : SomeClassBase
{
public T Data { get; set; }
// and more ....
}
class App
{
List<Action<SomeClassBase>> _actions = new List<Action<SomeClassBase>>();
void Add<T>( Action<SomeClass<T>> foo )
where T : SomeClassBase
{
_actions.Add( foo );
}
}
The compiler complains - for the _actions.Add() line;
Argument 1: cannot convert from 'System.Action<test.SomeClass<T>>' to 'System.Action<test.SomeClassBase>'
The best overloaded method match for 'System.Collections.Generic.List<System.Action<test.SomeClassBase>>.Add(System.Action<test.SomeClassBase>)' has some invalid arguments
From the application side there is no need for the SomeClassBase class, yet it seems impossible to define a List of Action<SomeClass<T>> elements and the approach with the base-class works when using the class in the List, instead of the Action
Thanks,
jochen
EDIT: Okay, now I see what you're trying to do. I've left the old answer below for posterity :)
Unfortunately you can't express the relationship you want in C# generics, but as you can make sure you're the only one manipulating the collection, you can keep it safe yourself:
Try this:
class App
{
private readonly Dictionary<Type, object> delegateMap;
void Add<T>(Action<SomeClass<T>> foo)
{
object tmp;
if (!delegateMap.TryGetValue(typeof(T), out tmp))
{
tmp = new List<Action<SomeClass<T>>>();
delegateMap[typeof(t)] = tmp;
}
List<Action<SomeClass<T>> list = (List<Action<SomeClass<T>>) tmp;
list.Add(foo);
}
void InvokeActions<T>(SomeClass<T> item)
{
object tmp;
if (delegateMap.TryGetValue(typeof(T), out tmp))
{
List<Action<SomeClass<T>> list = (List<Action<SomeClass<T>>) tmp;
foreach (var action in list)
{
action(item);
}
}
}
}
Note that you could use the fact that delegates are multicast to just keep a Dictionary<Type, Delegate> and combine them together, but I'll leave that as an exercise for the reader :)
Old answer
It's failing for a good reason. Let's get rid of the generics (as they're irrelevant here) and think about a simpler case - fruit and bananas.
You're trying to add an Action<Banana> to a List<Action<Fruit>>. You can't do that - even with the generic variance of C# 4. Why? Because it's not safe. Consider this:
Action<Banana> peeler = banana => banana.Peel();
List<Action<Fruit>> fruitActions = new List<Action<Fruit>>();
fruitActions.Add(peeler); // Nope!
fruitActions[0].Invoke(new Strawberry());
Eek! Now we've got a banana peeler trying to peel a strawberry... what a mess!
Not that the other way round would be acceptable in C# 4:
Action<Fruit> eater = fruit => fruit.Eat();
List<Action<Banana>> bananaActions = new List<Action<Banana>>();
fruitActions.Add(eater); // Yes!
fruitActions[0].Invoke(new Banana());
Here we're adding an Action<Fruit> to a List<Action<Banana>> - that's acceptable, because anything you can do to an Action<Banana> is also valid for an Action<Fruit>.
Will this do what you want?
void Add<T>(Action<SomeClass<T>> foo)
where T : SomeClassBase
{
_actions.Add(x => foo((SomeClass<T>) x));
}
using System;
using System.Collections.Generic;
public delegate void MyDelegate<T>( T i );
public class DelegateList<T>
{
public void Add( MyDelegate<T> del ) {
imp.Add( del );
}
public void CallDelegates( T k ) {
foreach( MyDelegate<T> del in imp ) {
del( k );
}
}
private List<MyDelegate<T> > imp = new List<MyDelegate<T> >();
}
public class MainClass
{
static void Main() {
DelegateList<int> delegates = new DelegateList<int>();
delegates.Add( PrintInt );
delegates.CallDelegates( 42 );
}
static void PrintInt( int i ) {
Console.WriteLine( i );
}
}
Not sure if this is what you want. But try to change you Add method to:
void Add( Action<SomeClassBase> foo )
{
_actions.Add( foo );
}
Update
This will allow you to do something like this:
App app = new App();
Action<SomeClass<int>> action = null; // Initilize it...
app.Add((Action<SomeClassBase>)action);
If you look at the line
List<Action<SomeClass<T>>> _actions = new List<Action<SomeClass<T>>>();
The class T that you are referring to hasn't been declared anywhere. In SomeClass you have the right declaration for a generic class but in your App class you haven't told it what T is in this particular instance.
In summary I don't think this is doing what you want it to. With generics its easiest to imagine that when the code has been compiled there is no such thing as generics[0]. That during the compilation its just making all the classes you are using generically. This means there isn't really a concept of a list of generic classes since by the time you are using them the classes are of a given type and so can't be mixed.
I think the way it would need to work is using more definite class definitions but as Jon Skeet explained that doesn't really work either.
Perhaps the best idea is to take a few step backs and ask a question about what you are doing with this messaging system?
[0] Generics work differently in different languages but this is a good rough principle to work on I think...
I don't know if this is what you want exactly but if you want to have a method which invoke an action for each element in a list you can use an extension method like that :
public static class Extensions
{
public static void Action<T>(this IEnumerable<T> list, Action<T> action)
{
foreach (T element in list)
{
action.Invoke(element);
}
}
}
An exemple of call with myList of type IEnumerable<string>:
myList.Action(element => Console.WriteLine(element));
Maybe LINQ already implements an action in a List but if it's the case I don't know the syntax.