Why aren't delegate instances always cached? - c#

Why does the C# compiler not create code which caches the delegate instance of Action(SomeMethod) in this case:
void MyMethod() {
Decorator(SomeMethod);
}
void Decorator(Action a) { a(); }
void SomeMethod() { }
It does it only when SomeMethod is static:
static void SomeMethod() { }
EDIT:
To be clearer, let's take the following code:
class A {
public void M1() {
var b = new B();
b.Decorate(M2);
}
public void M2() {
}
}
class B {
public void Decorate(Action a) {
Console.WriteLine("Calling");
a();
}
}
If you want to avoid the delegate allocation every time M1 is called, you can do it easily but it's quite ugly:
using System;
class A {
Action _m2;
public A() {
_m2 = new Action(M2);
}
public void M1() {
var b = new B();
b.Decorate(_m2);
}
public void M2() {
}
}
class B {
public void Decorate(Action a) {
Console.WriteLine("Calling");
a();
}
}
So my question was, what's the reason the compiler cannot generate a similar code? I can't see any side effects.
I'm not saying there's no reason, the people working on the compiler are much smarter than I will probably ever be. I'm only looking to understand which scenarios this won't work.

It can't cache it for instance methods because the target instance is part of the delegate, and it really wants to use a static field for the cache. A static method call that doesn't capture any variables etc can be cached very cheaply, but it gets a lot more complex when state is involved, and this counts as state.
Yes, I suppose is could use an instance field to cache () => this.SomeMethod(), but frankly, this being the target is a relatively rare case and doesn't solve the general problem.
However, it also only does this for lambda syntax, i.e. even if SomeMethod is static
Decorator(SomeMethod); // not cached
Decorator(() => SomeMethod()); // cached
You can see the difference here
This is because the difference is detectable (different object refs vs same object ref) and could in theory lead to different program behavior in existing code that used the original (non-lambda) syntax; so the cache provision has not to-date been applied retrospectively to the old syntax. Compatibility reasons. This has been discussed for years, though; IMO it is one of those things like the change to foreach L-value captures, that could probably be changed without breaking the world as much as we imagine.
To see the theoretical difference in an example based on the edited question:
using System;
class A
{
static void Main()
{
var obj = new A();
Console.WriteLine("With cache...");
for (int i = 0; i < 5; i++) obj.WithCache();
Console.WriteLine("And without cache...");
for (int i = 0; i < 5; i++) obj.WithoutCache();
}
Action _m2;
B b = new B();
public void WithCache() => b.Decorate(_m2 ??= M2);
public void WithoutCache() => b.Decorate(M2);
public void M2() => Console.WriteLine("I'm M2");
}
class B
{
private object _last;
public void Decorate(Action a)
{
if (_last != (object)a)
{
a();
_last = a;
}
else
{
Console.WriteLine("No do-overs!");
}
}
}
This currently outputs:
With cache...
I'm M2
No do-overs!
No do-overs!
No do-overs!
No do-overs!
And without cache...
I'm M2
I'm M2
I'm M2
I'm M2
I'm M2

Related

How to instantiate unique delegates using an anonymous method in a loop (in C#)?

Code:
using System.IO;
using System;
using System.Reflection;
using System.Collections.Generic;
class AnyClass
{
delegate void Del(string str);
static void Main()
{
List<Del> listDel = new List<Del>();
listDel.Add(delegate(string str) { });
Console.WriteLine( listDel[0].Method.ToString() );
listDel.Add(delegate(string str) { });
Console.WriteLine( listDel[1].Method.ToString() );
for (int i = 0; i < 2; i++)
{
listDel.Add(delegate(string str) { });
}
Console.WriteLine( listDel[2].Method.ToString() );
Console.WriteLine( listDel[3].Method.ToString() );
}
}
Output:
Void m__0(System.String)
Void m__1(System.String)
Void m__2(System.String)
Void m__2(System.String)
Why do the delegates instantiated in the loop "point" to the same method (m__2) whereas the ones instantiated outside the loop point to two different methods (m__0 and m__1)?
Is there any way how to instantiate delegates that point to different/unique methods inside a loop?
Example of usage: I need to have delegates as keys in a dictionary, so they need to be unique. Instantiation inside a loop is necessary to provide enough of flexibility.
Why do the delegates instantiated in the loop "point" to the same
method (m__2) whereas the ones instantiated outside the loop point to
two different methods (m__0 and m__1)?
Because behind the scenes the compiler is caching the delegate creation. When you create the first two delegates, the compiler doesn't have knowledge that they are the same, so he creates two different cached delegates and two named methods. Inside your for loop, the compiler is optimizing by only instantiating the delegate once. He can be certain that it's the same delegate each time, instantiate it once, then cache it.
When you de-compile your code, it actually looks like this:
private delegate void Del(string str);
[CompilerGenerated]
private static Launcher.Del CS$<>9__CachedAnonymousMethodDelegate3;
[CompilerGenerated]
private static Launcher.Del CS$<>9__CachedAnonymousMethodDelegate4;
[CompilerGenerated]
private static Launcher.Del CS$<>9__CachedAnonymousMethodDelegate5;
private static void Main()
{
List<Launcher.Del> listDel = new List<Launcher.Del>();
List<Launcher.Del> arg_24_0 = listDel;
if (Launcher.CS$<>9__CachedAnonymousMethodDelegate3 == null)
{
Launcher.CS$<>9__CachedAnonymousMethodDelegate3 =
new Launcher.Del(Launcher.<Main>b__0);
}
arg_24_0.Add(Launcher.CS$<>9__CachedAnonymousMethodDelegate3);
Console.WriteLine(listDel[0].Method.ToString());
List<Launcher.Del> arg_5D_0 = listDel;
if (Launcher.CS$<>9__CachedAnonymousMethodDelegate4 == null)
{
Launcher.CS$<>9__CachedAnonymousMethodDelegate4 =
new Launcher.Del(Launcher.<Main>b__1);
}
arg_5D_0.Add(Launcher.CS$<>9__CachedAnonymousMethodDelegate4);
Console.WriteLine(listDel[1].Method.ToString());
for (int i = 0; i < 2; i++)
{
List<Launcher.Del> arg_9A_0 = listDel;
if (Launcher.CS$<>9__CachedAnonymousMethodDelegate5 == null)
{
Launcher.CS$<>9__CachedAnonymousMethodDelegate5 =
new Launcher.Del(Launcher.<Main>b__2);
}
arg_9A_0.Add(Launcher.CS$<>9__CachedAnonymousMethodDelegate5);
Console.WriteLine(listDel[2 + i].Method.ToString());
}
}
[CompilerGenerated]
private static void <Main>b__0(string str)
{
}
[CompilerGenerated]
private static void <Main>b__1(string str)
{
}
[CompilerGenerated]
private static void <Main>b__2(string str)
{
}
I would definitely not rely on a delegate being a proper key for a Dictionary.
Is there any way how to instantiate delegates that point to
different/unique methods inside a loop?
You can force the delegate to be a "fresh instance" only by explicitly creating a new Del instance yourself and passing a new named method each time. There are other more "fishy" ways of doing so, but I wouldn't recommend taking those paths just to get a new delegate.
Is there any way how to instantiate delegates that point to different/unique methods inside a loop?
You can't make each loop iteration create a different method because methods are hard-coded into the assembly. Their number is fixed while the loop could be unbounded.
You can make each syntactic appearance of a lambda have a different method by using some kind of hack:
Action<int> x = i => {
if (Environment.CurrentManagedThreadId < 0 /*always false*/)
Console.WriteLine(i + uniqueIntegerHere);
};
This forces each method body to be unique and the compiler cannot ever optimize this away. You can of course pull the body into a helper method.
If you want unique delegates per loop iteration you either need to create methods at runtime or keep a set of statically compiled methods:
void F1() { }
void F2() { }
void F3() { }
...
T4 templates come to mind.
Yet another way similar to the one proposed by #usr. You can force compiler to create a new instance of delegate object using reflection method Delegate.CreateDelegate(type, this, methodInfo). The trick goes at the point where this parameter is always a new object thus forcing myMethod being called on it and thus each delegate actually represents a different context for compiler.
This requires the method for delegation to be inside a separate class, which you can instantiate. I am not sure this requirement fits you actual task. Perhaps you will be inspired for another solution based on this one...
using System.IO;
using System;
using System.Reflection;
using System.Collections.Generic;
class AnyClass
{
delegate void Del(string str);
private static Dictionary<Del, string> dict = new Dictionary<Del, string>();
static void Main()
{
List<Del> listDel = new List<Del>();
int count = 10;
for (int i = 0; i < count; i++)
{
listDel.Add(factory());
dict.Add(listDel[i ], "Delegate " + (i));
}
for (int i = 0; i < count; i++)
{
Console.WriteLine(listDel[i].Method.ToString());
listDel[i].Invoke((i).ToString());
}
Console.ReadLine();
}
public class DelegateEncapsulator
{
private int _number;
public DelegateEncapsulator(int number)
{
_number = number;
}
public void myMethod(string str) {
Console.WriteLine("Delegate " + _number + " " + str);
}
}
private static int delegateCounter = 100;
private static Del factory()
{
var obj = new DelegateEncapsulator(delegateCounter++);
var ret = (Del)Delegate.CreateDelegate(typeof(Del), obj,
typeof(DelegateEncapsulator).GetMethod("myMethod"));
return ret;
}
}
This code adds all delegates into a dictionary. You can play with number elements to be added.
Hope this helps

Guarantee that a class can only be used by the thread that instantiated it

I've created a class that is not thread-safe and can lead to bad bugs if assumed to be thread-safe. While I work to make my class thread-safe, I'd like to make instances only usable by one thread. Currently my implementation is to check that the current thread is the same as the thread used to construct the instance at every exposure point.
public class NotThreadSafeClass
{
private readonly int _creatorThreadId;
public NotThreadSafeClass()
{
_creatorThreadId = Thread.CurrentThread.ManagedThreadId;
}
public string ExposedProp
{
get
{
AssertSameThread();
return "My Prop";
}
}
public void ExposedMethod()
{
AssertSameThread();
/* Do stuff */
}
private void AssertSameThread()
{
Throw.If(_creatorThreadId != Thread.CurrentThread.ManagedThreadId,
#"NotThreadSafeClass is not thread safe. Please don't use
the same instance of NotThreadSafeClass in multiple threads.");
}
}
Note: Throw.If is defined in http://www.codeducky.org/10-utilities-c-developers-should-know-part-one/
This pattern seems to work, but it's cumbersome and susceptible to bugs if a developer forgets to add this check to any new exposures. Is there a safer and/or more elegant way to ensure that an instance is only used by one thread?
I think that short of using an AOP framework, you will have to "intercept" all such access to your class' methods/properties in your own code, just like you're describing.
I'm thinking Ninject's Interception Extension, or PostSharp
Nothing is built into the language/framework for this.
Cheers
Edit: Moved ThreadLocal<T> to a private field inside the class declaration.
Unless I completely misunderstand, ThreadLocal<T> should meet your needs. An example:
class Foo {
private ThreadLocal<int> _internalState;
public Foo() {
_internalState = new ThreadLocal<int>();
}
public int IntValue {
get { return _internalState.Value; }
set { _internalState.Value = value; }
}
public override string ToString() {
return _internalState.ToString();
}
}
class Program {
public static void Main(string[] args) {
Demonstrate();
}
static void Demonstrate() {
var local = new Foo {IntValue = 5};
Console.WriteLine("Start thread value: {0}", local.IntValue);
new Thread(() => {
local.IntValue += 5;
Console.WriteLine("New thread value: {0}", local.IntValue);
}).Start();
local.IntValue += 10;
Console.WriteLine("Start thread value: {0}", local.IntValue);
}
}
Sample output:
Start thread value: 5
Start thread value: 15
New thread value: 5

How Can i call other functions in a class from special function(Just with their string names) in C#?

I have a Class by name of GoldClass. It has four methods by names F(),S(),TH(),Fo(). In the methods FO(). I want to call three other methods (F,S,TH) but just use their names like this.
public void Fo()
{
list <string> FuncsList=new list<string>();
FuncsList.Add("F");
FuncsList.Add("S");
FuncsList.Add("TH");
//NOW I WANT TO CALL THEM BUT USE MY STRINGS IN MY FUNCSLIST
}
I used Reflection at first ... but I am assigning some values to public variables in my class..and when reflection make new instance all my data in public variables is lost.
Is there any particular reason, you need to store them as strings. If they're all parameterless void methods in the same class, you could store them as Actions
void Main()
{
A();
}
public void A()
{
List<Action> list = new List<Action>();
list.Add(B);
list.Add(C);
list.Add(D);
foreach(Action action in list){
action();
}
}
public void B()
{
Console.WriteLine("B Called");
}
public void C()
{
Console.WriteLine("C Called");
}
public void D()
{
Console.WriteLine("D Called");
}
Having said that, It's not at all clear why you need to do this at all. Why do you need to do this dynamically. would the following not suffice.
public void FO()
{
F();
S();
TH();
}
You can invoke a function with a string.
Check this link for more information
http://msdn.microsoft.com/en-us/library/system.type.invokemember.aspx
You could use a dictionary of strings and actions for this:
public class Example
{
private Dictionary<string, Action> _map = new Dictionary<string, Action>();
public Example()
{
_map["A"] = A;
_map["B"] = B;
_map["C"] = C;
}
public void A() { }
public void B() { }
public void C() { }
public void CallByString(string func)
{
if(_map.ContainsKey(func))
_map[func]();
}
}
Usage:
Example example = new Example();
example.CallByString("A");
You have two options:
Either use reflection.
Or use some kind of switch statement, the later is faster.
public void Fo()
{
list <string> FuncsList=new list<string>();
FuncsList.Add("F");
FuncsList.Add("S");
FuncsList.Add("TH");
foreach(String name in FuncsList)
CallNamedMethod(name);
}
private void CallNamedMethod(string name)
{
switch(name)
{
case "F":
F();
return;
case "S":
S();
return;
case "TH":
TH();
return;
default:
throw new InvalidArgumentException();
}
}
If you have a huge amount of different methods that you can call, you may create a dictionary with names and delegates.
Good luck with your quest.
Call Direct assembly where they belongs c# cannot know is their references

How do i change the call order of nested constructors (child before abstract parent)

The code below throws an exception because the abstract constructor is called before the child constructor.
I need to provide an abstract class to capsule some logic from a different part of the program. However i also need to check if the abstract members are initialised correctly rigth after creation without the childclass having any influence over this.
the compiling example below should illustrate my question.
using System;
namespace Stackoverflow
{
class Program
{
static void Main(string[] args)
{
var x = new Thing(5);
var y = new Child(x);
}
}
class Child : AbstractParent
{
Thing childthing;
public Child(Thing provided) : base(){
childthing = provided;
}
public override void Initialise(){
//Exception is thrown here - childthing is still null
parentthing = childthing.Add(1);
}
}
abstract class AbstractParent
{
protected Thing parentthing;
public AbstractParent(){
Initialise();
AssertThingyNotNull();
}
private void AssertThingyNotNull(){
if (parentthing == null) throw new Exception("Waaa");
}
public abstract void Initialise();
}
class Thing
{
private int i;
public Thing(int i){
this.i = i;
}
public Thing Add(int b){
i += b;
return new Thing(i);
}
}
}
Edit #1:
Is there some way to do this by reflecting into the caller (should be the creator of child rigth?) and then reacting on the end of that call?
Edit #2:
Getting the .ctor that creates the child is easy. Manipulating the methods seems something between impossible and a bad idea.
foreach (StackFrame frame in new StackTrace().GetFrames())
{
Console.WriteLine(frame.GetMethod().Name);
}
You can't, basically. This is why you should avoid calling virtual (or abstract) members from a constructor as far as possible - you could end up with code which is running with an incomplete context. Any variable initializers are executed before the base class constructor is called, but none of the code within the constructor body is.
If you need to perform initialization and only want to do that when the derived class constructor is running, then just call Initialise from the derived class constructor to start with.
You can do something similar to what Microsoft did with InitializeComponent()
then let the children call it whenever it can.
Try this.
Edited = cleaner version.
using System;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
var x = new Thing(5);
var y = new Child(x);
}
}
class Child : AbstractParent
{
public Child(Thing provided)
: base()
{
parentthing = provided;
base.Initialise();
}
}
abstract class AbstractParent
{
protected Thing parentthing;
public AbstractParent()
{
}
private void AssertThingyNotNull()
{
if (parentthing == null) throw new Exception("Waaa");
}
public void Initialise()
{
AssertThingyNotNull();
}
}
class Thing
{
private int i;
public Thing(int i)
{
this.i = i;
}
public Thing Add(int b)
{
i += b;
return new Thing(i);
}
}
}

What does the keyword this mean in C#, when talking about event handlers?

When I write an event handler for csharp, it looks like this:
public void FooHandler(object sender, EventArgs e)
{
//do stuff..
this.doSomething(); //Does the "this" keyword mean something in this context?
}
Does the "this" keyword mean something in this context?
EDIT:
Let's say I also have this code:
public class GizmoManager {
public void Manage() {
g = new Gizmo();
g.Foo += new EventHandler(FooHandler);
}
}
What would the this (within FooHandler) refer to?
Yes, it's a reference to object for which FooHandler() is called. Delegates are capable of referencing both static and non-static methods. When talking about non-static ones, this is a reference to object instance.
class A
{
public delegate void MyDelegate(object sender, int x);
public event MyDelegate TheEvent;
public void func()
{
if(TheEvent != null) TheEvent(this, 123);
}
}
class B
{
public B()
{
A a = new A();
a.TheEvent += handler;
a.func();
}
public void handler(object sender, int x)
{
// "sender" is a reference to object of type A that we've created in ctor
// "x" is 123
// "this" is a reference to B (b below)
}
}
B b = new B(); // here it starts
Some more details. Your code:
g = new Gizmo();
g.Foo += new EventHandler(FooHandler);
could be re-written like this
g = new Gizmo();
g.Foo += new EventHandler(this.FooHandler); // look here
In this case this is the same this that you have in your handler ;-)
And even more, if you have some problems with understanding this:
class X
{
int a;
public X(int b)
{
this.a = b; // this stands for "this object"
// a = b is absolutely the same
}
public X getItsThis()
{
return this;
}
}
X x = new X();
X x2 = x.getItsThis();
// x and x2 refer to THE SAME object
// there's still only one object of class X, but 2 references: x and x2
more complete...
public class Bar
{
public Bar()
{
Gizmo g = new Gizmo();
g.Foo += new EventHandler(FooHandler);
}
public void FooHandler(object sender, EventArgs e)
{
//do stuff..
this //Does the "this" keyword mean something in this context?
}
}
"this" will refer to an instance of Bar
this is going to refer to the current class you are in, not the method.
From MSDN,
The this keyword refers to the current instance of the class. Static
member functions do not have a this pointer. The this keyword can be
used to access members from within constructors, instance methods, and
instance accessors.
In your example, this.doSomething() refers to a method in some arbitrary class outside of that method. this is redundant.
It is useful to use this in cases like this:
public Employee(string name, string alias)
{
this.name = name;
this.alias = alias;
}
It helps delineate between the meaning. Otherwise, without this what name or alias are you really referring to?
Finally, sender is going to refer to the object which raised the event.

Categories

Resources