I have a simple question about .net delegates. Say I have something like this:
public void Invoke(Action<T> action)
{
Invoke(() => action(this.Value));
}
public void Invoke(Action action)
{
m_TaskQueue.Enqueue(action);
}
The first function encloses a reference to this.Value. During runtime, when the first, method with generic parameter gets called, it will provide this.Value somehow to the second one, but how? These came into my mind:
Call by value (struct) - the current value of this.Value gets passed, so if the m_TaskQueue executes it 5 minutes later, the value will not be in its recent state, it will be whatever it was when first referencing.
Call by reference (reference type) - then the most recent state of Value will be referenced during execution of action but if I change this.Value to another reference before execution of action, it will still be pointing to the old reference
Call by name (both) - where this.Value will be evaluated when the action gets called. I believe the actual implementation would be holding a reference to this then evaluate Value on that during actual execution of delegate since there is no call by name.
I assume it would be Call of name style but could not find any documentation so wondering if it is a well-defined behavior. This class is something like an Actor in Scala or Erlang so I need it to be thread safe. I do not want Invoke function to dereference Value immediately, that will be done in a safe thread for this object by m_TaskQueue.
Let me answer your question by describing what code we actually generate for this. I'll rename your confusingly-named other Invoke method; it's not necessary to understanding what's going on here.
Suppose you said
class C<T>
{
public T Value;
public void Invoke(Action<T> action)
{
Frob(() => action(this.Value));
}
public void Frob(Action action)
{ // whatever
}
}
The compiler generates code as though you had actually written:
class C<T>
{
public T Value;
private class CLOSURE
{
public Action<T> ACTION;
public C<T> THIS;
public void METHOD()
{
this.ACTION(this.THIS.Value);
}
}
public void Invoke(Action<T> action)
{
CLOSURE closure = new CLOSURE();
closure.THIS = this;
closure.ACTION = action;
Frob(new Action(closure.METHOD));
}
public void Frob(Action action)
{ // whatever
}
}
Does that answer your question?
The delegate stores a reference to the variable, not the value of it. If you want to keep the current value then (assuming it is a value type) you need to make a local copy of it:
public void Invoke(Action<T> action)
{
var localValue = this.Value;
Invoke(() => action(localValue));
}
If it is a mutable reference type you could make a local clone / deep copy.
The real key is to remember that scope is lexical; it's something the compiler takes care of. So it captures variables, not their values. Whether those values are value types or reference types is another matter completely.
Maybe a slightly more extreme example of altering the behavior of the delegate will help:
var myVariable = "something";
Action a = () => Console.WriteLine(myVariable);
myVariable = "something else entirely"
a();
prints "something else entirely". In that light, it doesn't really matter how many times you wrap, save, or move the function; it still refers to the variable it enclosed. So, in short, what matters is the value of the enclosed variable when the delegate's actually executed.
Related
I have a method that takes an Action as a parameter. Actions are stored in a queue and executed when particular resources become available. Before I invoke an Action, I'd like to check if the instance it is a member of is null.
I did a simple test with the following stupid example. The Action invoked successfully after setting the invokee to null, and as expected, I got a NullReferenceException when attempting to access the property on the null invokee. Nothing jumped out at me when examining the Action at runtime that suggested I could determine if its instance was null.
I guess I could pass in the Action and the instance as parameters and test if the instance is null before invoking. Is it possible to test for a null invokee, or is this just a case of bad design on my part?
UPDATE:
I added the line,
if (explosion.Target != null)
to Bazooka.Fire(), to check for a null target, but it is still invoking the delegate in my example.
public void LetsDoThis()
{
var bazooka = new Bazooka();
var rocketLauncher = new RocketLauncher();
bazooka.LockAndLoad(rocketLauncher.BlowStuffUp);
rocketLauncher = null;
bazooka.Fire();
bool wasThisCompletelyAwesome = rocketLauncher.ThisIsAwesome;
}
public class RocketLauncher
{
public void BlowStuffUp()
{
bool stuffIsBlowingUp = true;
}
public bool ThisIsAwesome
{
get
{
return true;
}
}
}
public class Bazooka
{
private List<Action> explosions = new List<Action>();
public void LockAndLoad(Action loadIt)
{
this.explosions.Add(loadIt);
}
public void Fire()
{
foreach (Action explosion in explosions)
if (explosion.Target != null)
explosion.Invoke();
}
}
This won't work.
The Action does not in any way care about the original reference variable you got it from, it makes a copy of the reference value, and thus has its own reference.
Note that this also means that as long as you still have a reference to the delegate, even though you have no other references to the original object, it will still not be eligible for garbage collection.
The .Target property refers to the instance on which the method that the delegate refers to should be invoked, basically the this "parameter" to that method.
Thus, to have a null target you need to get the delegate from a static method, try this in LINQPad:
void Main()
{
Action a = Static.StaticMethod;
(a.Target == null).Dump();
}
public static class Static
{
public static void StaticMethod() { }
}
You can see that the delegate carries its own instance with this LINQPad code:
void Main()
{
Dummy d = new Dummy { Name = "A" };
Action a = d.Method;
d = new Dummy { Name = "B" };
Action b = d.Method;
d = null;
a();
b();
}
public class Dummy
{
public string Name { get; set; }
public void Method()
{
Debug.WriteLine("Name=" + Name);
}
}
The output here will be
Name=A
Name=B
As requested, let me clarify the difference between the instance, the reference, and the variable.
When you construct an object instance, like this:
var rocketLauncher = new RocketLauncher();
What you're doing is calling a method known as a constructor. The return value from this constructor is a reference to the newly constructed object. Basically, it's a pointer, meaning a memory address of where in the memory that object now lives. If it makes it easier to understand the rest of this answer you can consider it to be just a number.
Additionally you declared a variable, rocketLauncher, to hold this reference, this number.
Note that the object is separate from the variable, they're two distinct items. In one place in memory you have an object, in another place you have the variable containing the reference to that object, it's address, that number.
So when you do this:
bazooka.LockAndLoad(rocketLauncher.BlowStuffUp);
Let's simplify it a bit:
Action a = rocketLauncher.BlowStuffUp;
// bazooka.LockAndLoad(a);
let's forget about the part where we call that LockAndLoad method, and look at what happened when we "converted" the method BlowStuffUp into a delegate of type Action.
Basically, two things was "grabbed":
Which method to make the delegate refer to
The object instance on which to call that method
You can liken this to the following code:
MethodReference = rocketLauncher.BlowStuffUp;
object target = rocketLauncher;
// wrap this into a delegate
This now means you have two references to that object, one lives in the rocketLauncher variable, the other now lives inside the delegate.
What you do with that variable does not in any way change the value of that delegate, it still points to the same object as before. Basically it made a copy of that number. That number is still sitting there inside the delegate.
This is pretty much exactly the same as this:
int a = 10;
int b = a;
a = 0;
// b is still 10
So, to conclude, the .Target property of the delegate does not in any way know, or care, about the original variable that you got the delegate from. A copy was made of the reference value from that original variable, into the delegate, and what you do with the variable afterwards makes no difference at all.
So basically:
The instance is the object, it lives somewhere in memory
The reference is basically the address to it, and you can look at it as sort of a number
The variable is one place where you can store that reference
Now, what if you really want to make the delegate depend on the variable, and care about the value it now has, when you get around to calling it?
Well, one way would be to do this:
bazooka.LockAndLoad(delegate
{
if (rocketLauncher != null)
rocketLauncher.BlowStuffUp();
});
This would make an anonymous method, that would capture the variable itself, and then inside that anonymous method you could explicitly check what value the variable has at the time you call the delegate. If this part, about an anonymous method, does not make sense, you should ask another question here (ideally after reading a bit about anonymous methods, captured variables, and looked over some of the existing questions here on SO).
To test out an anonymous method, test the following code in LINQPad:
void Main()
{
object dummy = new object();
Action a = delegate
{
if (dummy != null)
Debug.WriteLine("not null");
else
Debug.WriteLine("null");
};
a();
dummy = null;
a();
}
It will print out:
not null
null
Use the Target property to check:
if(yourAction.Target != null) {
//...
}
Any Delegate type has a property called Target, so you can also use this for other types of delegate.
Update: In fact, when you use your Action to wrap some method of an object, that object won't never be disposed and that means the NullReferenceException can't be thrown in that case Unless you wrap another method of another object and this method has something to do with the null object.
Well, not in any way trying to argue with Lasse's rather detailed response, I would like to throw in my 5 cents on this.
When you invoke the LockAndLoad method of the bazooka class you simply add the method that's passed to the method to the List explosions collection of the bazooka class. Nulling the instantiation of the class whose method you had passed to the LockAndLoad method (in your example 'rocketLauncher') has NO effect on that collection, meaning that the Target property of the specific Action will not become null. You would have to explicitly remove the method from that collection BEFORE nulling the instantiation of the class.
bazooka.Unload(rocketLauncher.BlowStuffUp);
rocketLauncher = null;
Of course this works only if you modified your bazooka class to the following method in your bazooka class:
public void Unload(Action unloadIt)
{
if (explosions.Contains(unloadIt))
explosions.Remove(unloadIt);
}
This may not be what you are hoping for, but I hope it helped anyhow.
I've been using something similar to this whenever I needed to reference a Value type:
public class RefHost<T> {
public RefHost(T val)
{
Value = val;
}
private T _value;
public T Value {
get {
return _value;
}
set {
_value = value;
}
}
}
What I'm wondering is there a built in way or an easier way to use an existing Value type as a Reference type?
Example:
public class Editor {
public RefHost<int> Blah = new RefHost<int>(5);
// Some kind of timer to increase the value of Blah every few ticks
}
Kind of like that where the user of Editor specifies a value type that needs to be changed, and there can be multiple instances of Editor each with it's own value. I used the timer as an example but most of the time it's a user control like a slider.
I think you are looking for Tuple.
Sure there is. If you want to pass it as a reference type to a method just use the ref modifier:
public static void Main()
{
int n = 1;
Test(ref n);
Console.WriteLine(n); //will print out 2 and not 1.
Console.ReadKey(true);
}
public static void Test(ref int x)
{
x = 2;
}
What's wrong with this?
public class Editor {
public int Blah = 5;
// Some kind of timer, with a handler like:
void MyTimerTicker(object sender, EventArgs e)
{
this.Blah += 1;
}
}
Boxing and unboxing is what this is called. Your solution might be more type safe though.
See http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx
Replace the property and backing field with a public field. While it is generally good for classes to use properties rather than fields, the whole purpose of your type is to be a simple mutable container for a single value-type instance; the state encapsulated by any reference to an instance of the type should be precisely defined by two things:
The value of the `Value` member
The whereabouts of all other references to the instance that exist anywhere in the universe
If two instances have the same Value, and if within the entire universe only one reference exists to each one, the two references should be semantically indistinguishable [since in both cases the set of "other references" that exist to the instances would be empty]
While there are various helper methods that a type of that style might implement, it would be impossible for a future version of the type to add additional state without violating the expected semantics. Since the whole purpose of the type is to behave like a class object containing a single field of type T, code will be clearest if one writes the object to in fact be a class object containing a single field of type T.
BTW, if you don't want to define a custom type, another option is to use a single-element T[1]. That will use a little bit of extra storage to hold the dimension, and adding [0] to all references will be a little uglier than .Value, but such an approach will nonetheless work pretty simply.
I have the following code:
public double CalculateDailyProjectPullForceMax(DateTime date, string start = null, string end = null)
{
Log("Calculating Daily Pull Force Max...");
var pullForceList = start == null
? _pullForce.Where((t, i) => _date[i] == date).ToList() // implicitly captured closure: end, start
: _pullForce.Where(
(t, i) => _date[i] == date && DateTime.Compare(_time[i], DateTime.Parse(start)) > 0 &&
DateTime.Compare(_time[i], DateTime.Parse(end)) < 0).ToList();
_pullForceDailyMax = Math.Round(pullForceList.Max(), 2, MidpointRounding.AwayFromZero);
return _pullForceDailyMax;
}
Now, I've added a comment on the line that ReSharper is suggesting a change. What does it mean, or why would it need to be changed? implicitly captured closure: end, start
The warning tells you that the variables end and start stay alive as any of the lambdas inside this method stay alive.
Take a look at the short example
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
int i = 0;
Random g = new Random();
this.button1.Click += (sender, args) => this.label1.Text = i++.ToString();
this.button2.Click += (sender, args) => this.label1.Text = (g.Next() + i).ToString();
}
I get an "Implicitly captured closure: g" warning at the first lambda. It is telling me that g cannot be garbage collected as long as the first lambda is in use.
The compiler generates a class for both lambda expressions and puts all variables in that class which are used in the lambda expressions.
So in my example g and i are held in the same class for execution of my delegates. If g is a heavy object with a lot of resources left behind, the garbage collector couldn't reclaim it, because the reference in this class is still alive as long as any of the lambda expressions is in use. So this is a potential memory leak, and that is the reason for the R# warning.
#splintor
As in C# the anonymous methods are always stored in one class per method there are two ways to avoid this:
Use an instance method instead of an anonymous one.
Split the creation of the lambda expressions into two methods.
Agreed with Peter Mortensen.
The C# compiler generates only one type that encapsulates all variables for all lambda expressions in a method.
For example, given the source code:
public class ValueStore
{
public Object GetValue()
{
return 1;
}
public void SetValue(Object obj)
{
}
}
public class ImplicitCaptureClosure
{
public void Captured()
{
var x = new object();
ValueStore store = new ValueStore();
Action action = () => store.SetValue(x);
Func<Object> f = () => store.GetValue(); //Implicitly capture closure: x
}
}
The compiler generates a type looks like :
[CompilerGenerated]
private sealed class c__DisplayClass2
{
public object x;
public ValueStore store;
public c__DisplayClass2()
{
base.ctor();
}
//Represents the first lambda expression: () => store.SetValue(x)
public void Capturedb__0()
{
this.store.SetValue(this.x);
}
//Represents the second lambda expression: () => store.GetValue()
public object Capturedb__1()
{
return this.store.GetValue();
}
}
And the Capture method is compiled as:
public void Captured()
{
ImplicitCaptureClosure.c__DisplayClass2 cDisplayClass2 = new ImplicitCaptureClosure.c__DisplayClass2();
cDisplayClass2.x = new object();
cDisplayClass2.store = new ValueStore();
Action action = new Action((object) cDisplayClass2, __methodptr(Capturedb__0));
Func<object> func = new Func<object>((object) cDisplayClass2, __methodptr(Capturedb__1));
}
Though the second lambda does not use x, it cannot be garbage collected as x is compiled as a property of the generated class used in the lambda.
The warning is valid and displayed in methods that have more than one lambda, and they capture different values.
When a method that contains lambdas is invoked, a compiler-generated object is instantiated with:
instance methods representing the lambdas
fields representing all values captured by any of those lambdas
As an example:
class DecompileMe
{
DecompileMe(Action<Action> callable1, Action<Action> callable2)
{
var p1 = 1;
var p2 = "hello";
callable1(() => p1++); // WARNING: Implicitly captured closure: p2
callable2(() => { p2.ToString(); p1++; });
}
}
Examine the generated code for this class (tidied up a little):
class DecompileMe
{
DecompileMe(Action<Action> callable1, Action<Action> callable2)
{
var helper = new LambdaHelper();
helper.p1 = 1;
helper.p2 = "hello";
callable1(helper.Lambda1);
callable2(helper.Lambda2);
}
[CompilerGenerated]
private sealed class LambdaHelper
{
public int p1;
public string p2;
public void Lambda1() { ++p1; }
public void Lambda2() { p2.ToString(); ++p1; }
}
}
Note the instance of LambdaHelper created stores both p1 and p2.
Imagine that:
callable1 keeps a long-lived reference to its argument, helper.Lambda1
callable2 does not keep a reference to its argument, helper.Lambda2
In this situation, the reference to helper.Lambda1 also indirectly references the string in p2, and this means that the garbage collector will not be able to deallocate it. At worst it is a memory/resource leak. Alternatively it may keep object(s) alive longer than otherwise needed, which can have an impact on GC if they get promoted from gen0 to gen1.
For Linq to Sql queries, you may get this warning. The lambda's scope may outlive the method due to the fact that the query is often actualized after the method is out of scope. Depending on your situation, you may want to actualize the results (i.e. via .ToList()) within the method to allow for GC on the method's instance vars captured in the L2S lambda.
You could always figure out with a reasons of R# suggestions just by clicking on the hints like shown below:
This hint will direct you here.
This inspection draws your attention to the fact that more closure
values are being captured than is obviously visibly, which has an
impact on the lifetime of these values.
Consider the following code:
using System;
public class Class1 {
private Action _someAction;
public void Method() {
var obj1 = new object();
var obj2 = new object();
_someAction += () => {
Console.WriteLine(obj1);
Console.WriteLine(obj2);
};
// "Implicitly captured closure: obj2"
_someAction += () => {
Console.WriteLine(obj1);
};
}
}
In the first closure, we see that both obj1 and obj2 are being explicitly captured; we can see this just by looking at the code. For
the second closure, we can see that obj1 is being explicitly captured,
but ReSharper is warning us that obj2 is being implicitly captured.
This is due to an implementation detail in the C# compiler. During
compilation, closures are rewritten into classes with fields that hold
the captured values, and methods that represent the closure itself.
The C# compiler will only create one such private class per method,
and if more than one closure is defined in a method, then this class
will contain multiple methods, one for each closure, and it will also
include all captured values from all closures.
If we look at the code that the compiler generates, it looks a little
like this (some names have been cleaned up to ease reading):
public class Class1 {
[CompilerGenerated]
private sealed class <>c__DisplayClass1_0
{
public object obj1;
public object obj2;
internal void <Method>b__0()
{
Console.WriteLine(obj1);
Console.WriteLine(obj2);
}
internal void <Method>b__1()
{
Console.WriteLine(obj1);
}
}
private Action _someAction;
public void Method()
{
// Create the display class - just one class for both closures
var dc = new Class1.<>c__DisplayClass1_0();
// Capture the closure values as fields on the display class
dc.obj1 = new object();
dc.obj2 = new object();
// Add the display class methods as closure values
_someAction += new Action(dc.<Method>b__0);
_someAction += new Action(dc.<Method>b__1);
}
}
When the method runs, it creates the display class, which captures all values, for all closures. So even if a value isn't used
in one of the closures, it will still be captured. This is the
"implicit" capture that ReSharper is highlighting.
The implication of this inspection is that the implicitly captured
closure value will not be garbage collected until the closure itself
is garbage collected. The lifetime of this value is now tied to the
lifetime of a closure that does not explicitly use the value. If the
closure is long lived, this might have a negative effect on your code,
especially if the captured value is very large.
Note that while this is an implementation detail of the compiler, it
is consistent across versions and implementations such as Microsoft
(pre and post Roslyn) or Mono's compiler. The implementation must work
as described in order to correctly handle multiple closures capturing
a value type. For example, if multiple closures capture an int, then
they must capture the same instance, which can only happen with a
single shared private nested class. The side effect of this is that
the lifetime of all captured values is now the maximum lifetime of any
closure that captures any of the values.
I currently have a switch statement that runs around 300 odd lines. I know this is not as giant as it can get, but I'm sure there's a better way to handle this.
The switch statement takes an Enum that is used to determine certain properties that pertain to logging. Right now the problem sets in that it is very easy to leave out an enumeration value and that it will not be given a value as it is not in the switch statement.
Is there an option one can use to ensure that every enumeration is used and given a custom set of values it needs to do its job?
EDIT:
Code sample as requested: (This is simplistic, but shows exactly what I mean. Also an Enumeration would exist with the below values.)
internal void GenerateStatusLog(LogAction ActionToLog)
{
switch (ActionToLog)
{
case LogAction.None:
{
return;
}
case LogAction.LogThis:
{
ActionText = "Logging this Information";
LogText = "Go for it.";
break;
}
}
// .. Do everything else
}
EDIT
I thought this over again, looked around in related questions in SO, and I wrote some code. I created a class named AdvancedSwitch<T>, which allows you to add cases and exposes a method to evaluate a value and lets you specify values that it should check for existence.
This is what I came up with:
public class AdvancedSwitch<T> where T : struct
{
protected Dictionary<T, Action> handlers = new Dictionary<T, Action>();
public void AddHandler(T caseValue, Action action)
{
handlers.Add(caseValue, action);
}
public void RemoveHandler(T caseValue)
{
handlers.Remove(caseValue);
}
public void ExecuteHandler(T actualValue)
{
ExecuteHandler(actualValue, Enumerable.Empty<T>());
}
public void ExecuteHandler(T actualValue, IEnumerable<T> ensureExistence)
{
foreach (var val in ensureExistence)
if (!handlers.ContainsKey(val))
throw new InvalidOperationException("The case " + val.ToString() + " is not handled.");
handlers[actualValue]();
}
}
You can consume the class this way:
public enum TrafficColor { Red, Yellow, Green }
public static void Main()
{
Console.WriteLine("Choose a traffic color: red, yellow, green?");
var color = (TrafficColor)Enum.Parse(typeof(TrafficColor), Console.ReadLine());
var result = string.Empty;
// Creating the "switch"
var mySwitch = new AdvancedSwitch<TrafficColor>();
// Adding a single case
mySwitch.AddHandler(TrafficColor.Green, delegate
{
result = "You may pass.";
});
// Adding multiple cases with the same action
Action redAndYellowDelegate = delegate
{
result = "You may not pass.";
};
mySwitch.AddHandler(TrafficColor.Red, redAndYellowDelegate);
mySwitch.AddHandler(TrafficColor.Yellow, redAndYellowDelegate);
// Evaluating it
mySwitch.ExecuteHandler(color, (TrafficColor[])Enum.GetValues(typeof(TrafficColor)));
Console.WriteLine(result);
}
With the creative use of anonymous delegates, you can easily add new cases to your "switch block". :)
Not that you can also use lambda expressions, and lambda blocks, eg () => { ... } instead of delegate { ... }.
You can easily use this class instead of the long switch blocks.
Original post:
If you use Visual Studio, always create swich statements with the switch code snippet. Type switch press tab twice, and it auto-generates all the possibilities for you.
Then, add a default case to the end which throws an exception, that way when testing your app you will notice that there is an unhandled case, instantly.
I mean something like this:
switch (something)
{
...
case YourEnum.SomeValue:
...
break;
default:
throw new InvalidOperationException("Default case reached.");
}
Well, there's throwing in the default case... There's no edit / compile time construct other than that.
However Strategy, Visitor and other patterns related to them may be appropriate if you choose to do it at run time.
Sample code will help with getting the best answer.
EDIT: Thanks for the sample. I still think it needs a bit of fleshing out as you dont cover whether there are some parameters that only apply to some cases etc.
Action is often used as an alias for the Command pattern and the fact that your Enum is called LogAction signifies that each value carries with it a behavior - be that implied (you stick appropriate code in a case) or explicit (in the specific Command hierarchy class).
Thus it looks to me like a usage of the Command pattern is appropriate (though your sample doesnt prove it) - i.e., have a class (potentially a hierarchy using constructor overloads or any other [set of] factory mechanisms) that keeps the state associated with the request along with the specific behaviour. Then, instead of passing an Enum value, create an appropriate LogCommand instance to the logger, which just invokes it (potentially passing a Log Sink 'receptacle' which the Command can log into). Otherwise you're poking random subsets of parameters in different places.
SEEALSO related posts:
C# - Is there a better alternative than this to ‘switch on type’?
Replace giant switch statement with what?
One possible solution is to use a SortedDictionary:
delegate void EnumHandler (args);
SortedDictionary <Enum, EnumHandler> handlers;
constructor
{
handlers = new SortedDictionary <Enum, EnumHandler> ();
fill in handlers
}
void SomeFunction (Enum enum)
{
EnumHandler handler;
if (handlers.TryGetValue (enum, out handler))
{
handler (args);
}
else
{
// not handled, report an error
}
}
This method does allow you to replace the handlers dynamically. You could also use a List as the value part of the dictionary and have multiple handlers for each enum.
Try to use reflection.
Decorate enum options with attributes that holds associated value and return this value.
Create static class of constants and use reflection for mapping enum-option to constant by name
hope this will help
Some times storing the options in a map is a good solution, you can externalize the configuration to a file too, not sure if it applies to your application.
Long code example here, and the final generic code is a little heavy (EDIT have added an extra example that eliminates the need for the angle brackets at the expense of some final flexibility).
One thing that this solution will give you is good performance - not quite as good as a straightforward switch statement, but each case statement becomes a dictionary lookup and method invocation, so still pretty good. The first call will get a performance penalty, however, due to the use of a static generic that reflects on initialisation.
Create an attribute and generic type as follows:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class DynamicSwitchAttribute : Attribute
{
public DynamicSwitchAttribute(Type enumType, params object[] targets)
{ Targets = new HashSet<object>(targets); EnumType = enumType; }
public Type EnumType { get; private set; }
public HashSet<object> Targets { get; private set; }
}
//this builds a cache of methods for a given TTarget type, with a
//signature equal to TAction,
//keyed by values of the type TEnum. All methods are expected to
//be instance methods.
//this code can easily be modified to support static methods instead.
//what would be nice here is if we could enforce a generic constraint
//on TAction : Delegate, but we can't.
public static class DynamicSwitch<TTarget, TEnum, TAction>
{
//our lookup of actions against enum values.
//note: no lock is required on this as it is built when the static
//class is initialised.
private static Dictionary<TEnum, TAction> _actions =
new Dictionary<TEnum, TAction>();
private static MethodInfo _tActionMethod;
private static MethodInfo TActionMethod
{
get
{
if (_tActionMethod == null)
{
//one criticism of this approach might be that validation exceptions
//will be thrown inside a TypeInitializationException.
_tActionMethod = typeof(TAction).GetMethod("Invoke",
BindingFlags.Instance | BindingFlags.Public);
if (_tActionMethod == null)
throw new ArgumentException(/*elided*/);
//verify that the first parameter type is compatible with our
//TTarget type.
var methodParams = _tActionMethod.GetParameters();
if (methodParams.Length == 0)
throw new ArgumentException(/*elided*/);
//now check that the first parameter is compatible with our type TTarget
if (!methodParams[0].ParameterType.IsAssignableFrom(typeof(TTarget)))
throw new ArgumentException(/*elided*/);
}
return _tActionMethod;
}
}
static DynamicSwitch()
{
//examine the type TTarget to extract all public instance methods
//(you can change this to private instance if need be) which have a
//DynamicSwitchAttribute defined.
//we then project the attributes and the method into an anonymous type
var possibleMatchingMethods =
from method in typeof(TTarget).
GetMethods(BindingFlags.Public | BindingFlags.Instance)
let attributes = method.GetCustomAttributes(
typeof(DynamicSwitchAttribute), true).
Cast<DynamicSwitchAttribute>().ToArray()
where attributes!= null && attributes.Length == 1
&& attributes[0].EnumType.Equals(typeof(TEnum))
select new { Method = method, Attribute = attributes[0] };
//create linq expression parameter expressions for each of the
//delegate type's parameters
//these can be re-used for each of the dynamic methods we generate.
ParameterExpression[] paramExprs = TActionMethod.GetParameters().
Select((pinfo, index) =>
Expression.Parameter(
pinfo.ParameterType, pinfo.Name ?? string.Format("arg{0}"))
).ToArray();
//pre-build an array of these parameter expressions that only
//include the actual parameters
//for the method, and not the 'this' parameter.
ParameterExpression[] realParamExprs = paramExprs.Skip(1).ToArray();
//this has to be generated for each target method.
MethodCallExpression methodCall = null;
foreach (var match in possibleMatchingMethods)
{
if (!MethodMatchesAction(match.Method))
continue;
//right, now we're going to use System.Linq.Expressions to build
//a dynamic expression to invoke this method given an instance of TTarget.
methodCall =
Expression.Call(
Expression.Convert(
paramExprs[0], typeof(TTarget)
),
match.Method, realParamExprs);
TAction dynamicDelegate = Expression.
Lambda<TAction>(methodCall, paramExprs).Compile();
//now we have our method, we simply inject it into the dictionary, using
//all the unique TEnum values (from the attribute) as the keys
foreach (var enumValue in match.Attribute.Targets.OfType<TEnum>())
{
if (_actions.ContainsKey(enumValue))
throw new InvalidOperationException(/*elided*/);
_actions[enumValue] = dynamicDelegate;
}
}
}
private static bool MethodMatchesAction(MethodInfo method)
{
//so we want to check that the target method matches our desired
//delegate type (TAction).
//The way this is done is to fetch the delegate type's Invoke
//method (implicitly invoked when you invoke delegate(args)), and
//then we check the return type and parameters types of that
//against the return type and args of the method we've been passed.
//if the target method's return type is equal to or derived from the
//expected delegate's return type, then all is good.
if (!_tActionMethod.ReturnType.IsAssignableFrom(method.ReturnType))
return false;
//now, the parameter lists of the method will not be equal in length,
//as our delegate explicitly includes the 'this' parameter, whereas
//instance methods do not.
var methodParams = method.GetParameters();
var delegateParams = TActionMethod.GetParameters();
for (int i = 0; i < methodParams.Length; i++)
{
if (!methodParams[i].ParameterType.IsAssignableFrom(
delegateParams[i + 1].ParameterType))
return false;
}
return true;
}
public static TAction Resolve(TEnum value)
{
TAction result;
if (!_actions.TryGetValue(value, out result))
throw new ArgumentException("The value is not mapped");
return result;
}
}
Now do this in a Unit Test:
[TestMethod]
public void TestMethod1()
{
Assert.AreEqual(1,
DynamicSwitch<UnitTest1, Blah, Func<UnitTest1, int>>.
Resolve(Blah.BlahBlah)(this));
Assert.AreEqual(125,
DynamicSwitch<UnitTest1, Blah, Func<UnitTest1, int>>.
Resolve(Blah.Blip)(this));
Assert.AreEqual(125,
DynamicSwitch<UnitTest1, Blah, Func<UnitTest1, int>>.
Resolve(Blah.Bop)(this));
}
public enum Blah
{
BlahBlah,
Bloo,
Blip,
Bup,
Bop
}
[DynamicSwitchAttribute(typeof(Blah), Blah.BlahBlah)]
public int Method()
{
return 1;
}
[DynamicSwitchAttribute(typeof(Blah), Blah.Blip, Blah.Bop)]
public int Method2()
{
return 125;
}
So, given a value of TEnum, and your preferred 'action' type (in your code you would appear to be simply returning nothing and modifying the internal state of the class), you simply consult the DynamicSwitch<> class, ask it to resolve a target method, and then invoke it inline (passing the target object on which the method will be invoked as the first parameter).
I'm not really expecting any votes for this - it's a MAD solution to be honest (it does have the advantage of being able to be applied for any enum type, and even discreet values of type int/float/double, as well as supporting any delegate type) - so perhaps it's a bit of a sledgehammer!
EDIT
Once you have a static generic like this, angle-bracket hell ensues - so we want to try and get rid of them. A lot of the time, this is done by type inference on method parameters etc - but we have a problem here that we can't easily infer a delegate's signature without repeating the method call i.e. (args) => return.
However, you seem to require a method that takes no parameters and returns void, so you can close over this behemoth generic by fixing the delegate type to Action, and throw a fluid API into the mix as well (if that's your kind of thing):
public static class ActionSwitch
{
public class SwitchOn<TEnum>
{
private TEnum Value { get; set; }
internal SwitchOn(TEnum value)
{
Value = value;
}
public class Call<TTarget>{
private TEnum Value { get; set; }
private TTarget Target { get; set; }
internal Call(TEnum value, TTarget target)
{
Value = value;
Target = target;
Invoke();
}
internal void Invoke(){
DynamicSwitch<TTarget, TEnum, Action<TTarget>>.Resolve(Value)(Target);
}
}
public Call<TTarget> On<TTarget>(TTarget target)
{
return new Call<TTarget>(Value, target);
}
}
public static SwitchOn<TEnum> Switch<TEnum>(TEnum onValue)
{
return new SwitchOn<TEnum>(onValue);
}
}
Now add this to the test project:
[TestMethod]
public void TestMethod2()
{
//no longer have any angle brackets
ActionSwitch.Switch(Blah.Bup).On(this);
Assert.IsTrue(_actionMethod1Called);
}
private bool _actionMethod1Called;
[DynamicSwitch(typeof(Blah), Blah.Bup)]
public void ActionMethod1()
{
_actionMethod1Called = true;
}
Only issue with this (apart from the complexity of the solution :) ) is that you'd have to re-build this static wrapper type whenever you want to use a new type of target delegate for a dynamic switch elsewhere. You could generate a generic version based on the Action<...> and Func<...> delegates that incorporates TArg1, TArg(n) and TReturn (if Func<>) - but you'd end up writing a lot more code.
Perhaps I'll turn this into an article on my blog and do all of that - if I get the time!
I want to have a library that will have a function in it that accepts an object for it's parameter.
With this object I want to be able to call a specified function when X is finished. The function that will be called is to be specified by the caller, and X will be done and monitored by the library.
How can I do this?
For reference I'm using C# and .NET 3.5
Two options for you:
Have the function accept a delegate (Action for a callback that doesn't return anything, Func for one that does) and use an anonymous delegate or Lambda Expression when calling it.
Use an interface
Using a delegate/lambda
public static void DoWork(Action processAction)
{
// do work
if (processAction != null)
processAction();
}
public static void Main()
{
// using anonymous delegate
DoWork(delegate() { Console.WriteLine("Completed"); });
// using Lambda
DoWork(() => Console.WriteLine("Completed"));
}
If your callback needs to have something passed to it, you can use a type parameter on Action:
public static void DoWork(Action<string> processAction)
{
// do work
if (processAction != null)
processAction("this is the string");
}
public static void Main()
{
// using anonymous delegate
DoWork(delegate(string str) { Console.WriteLine(str); });
// using Lambda
DoWork((str) => Console.WriteLine(str));
}
If it needs multiple arguments, you can add more type parameters to Action. If you need a return type, as mentioned use Func and make the return type the last type parameter (Func<string, int> is a function accepting a string and returning an int.)
More about delegates here.
Using an interface
public interface IObjectWithX
{
void X();
}
public class MyObjectWithX : IObjectWithX
{
public void X()
{
// do something
}
}
public class ActionClass
{
public static void DoWork(IObjectWithX handlerObject)
{
// do work
handlerObject.X();
}
}
public static void Main()
{
var obj = new MyObjectWithX()
ActionClass.DoWork(obj);
}
Sounds like a perfect recipe for delegates - in particular, callbacks with delegates are exactly how this is handled in the asynchronous pattern in .NET.
The caller would usually pass you some state and a delegate, and you store both of them in whatever context you've got, then call the delegate passing it the state and whatever result you might have.
You could either make the state just object or potentially use a generic delegate and take state of the appropriate type, e.g.
public delegate void Callback<T>(T state, OperationResult result)
Then:
public void DoSomeOperation(int otherParameterForWhateverReason,
Callback<T> callback, T state)
As you're using .NET 3.5 you might want to use the existing Func<...> and Action<...>
delegate types, but you may find it makes it clearer to declare your own. (The name may make it clearer what you're using it for.)
The object in question will need to implement an interface provided by you. Take the interface as a parameter, and then you can call any method that the interface exposes. Otherwise you have no way of knowing what the object is capable of. That, or you could take a delegate as a parameter and call that.
Is there a reason not to have your library provide a public event to be fired when the operation is complete? Then the caller could just register to handle the event and you don't have to worry about passing around objects or delegates.
The object implementing an interface you have provided would work, but it seems to be more the Java approach than the .NET approach. Events seem a bit cleaner to me.
You can use System.Action available in C#.NET for callback functions. Please check this sample example:
//Say you are calling some FUNC1 that has the tight while loop and you need to
//get updates on what percentage the updates have been done.
private void ExecuteUpdates()
{
Func1(Info => { lblUpdInfo.Text = Info; });
}
//Now Func1 would keep calling back the Action specified in the argument
//This System.Action can be returned for any type by passing the Type as the template.
//This example is returning string.
private void Func1(System.Action<string> UpdateInfo)
{
int nCount = 0;
while (nCount < 100)
{
nCount++;
if (UpdateInfo != null) UpdateInfo("Counter: " + nCount.ToString());
//System.Threading.Thread.Sleep(1000);
}
}