Reputation: 4522
I recently came across on such piece of code (here is simplified version, which I checked and it works):
using System;
using System.Threading;
namespace Rextester
{
public class Program
{
public class Foo
{
public Foo()
{
thread = new Thread(new ThreadStart(Loop));
}
private void Loop()
{
}
private Thread thread;
}
public static void Main(string[] args)
{
var foo = new Foo();
Console.WriteLine("How does it work??");
}
}
}
Why does such code work without any complains from compiler? As I understand, Thread should start from function which should be static. (or reference to object and member function should be passed anyway). But here I see only passing reference to member function. It seems like I missed big thing in c#. May be there is implicit way of passing this
reference?
UPD: great thanks. I just want to add minor addition of this fact. It turns out that compiler automatically handles delegates (passes correct reference object and method). here is il code:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 32 (0x20)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0
IL_0009: ldarg.0
IL_000a: ldftn instance void Rextester.Program/Foo::Loop()
IL_0010: newobj instance void
[mscorlib]System.Threading.ThreadStart::.ctor(object,
native int)
IL_0015: newobj instance void
[mscorlib]System.Threading.Thread::.ctor(class
[mscorlib]System.Threading.ThreadStart)
IL_001a: stfld class [mscorlib]System.Threading.Thread
Rextester.Program/Foo::thread
IL_001f: ret
} // end of method Foo::.ctor
Upvotes: 3
Views: 3154
Reputation: 23732
But here I see only passing reference to member function.
The documentation says to the ThreadStart that it is a delegate. It
"represents the method that executes on a Thread.
When a managed thread is created, the method that executes on the thread is represented by a ThreadStart delegate"
Thread should start from function which should be static.
This is not necessarily true. The function does not have to be static.
The documentation shows both examples. Using a static method and using an instance method:
class Test
{
static void Main()
{
// To start a thread using a static thread procedure, use the
// class name and method name when you create the ThreadStart
// delegate. Beginning in version 2.0 of the .NET Framework,
// it is not necessary to create a delegate explicitly.
// Specify the name of the method in the Thread constructor,
// and the compiler selects the correct delegate. For example:
//
// Thread newThread = new Thread(Work.DoWork);
//
ThreadStart threadDelegate = new ThreadStart(Work.DoWork);
Thread newThread = new Thread(threadDelegate);
newThread.Start();
// To start a thread using an instance method for the thread
// procedure, use the instance variable and method name when
// you create the ThreadStart delegate. Beginning in version
// 2.0 of the .NET Framework, the explicit delegate is not
// required.
//
Work w = new Work();
w.Data = 42;
threadDelegate = new ThreadStart(w.DoMoreWork);
newThread = new Thread(threadDelegate);
newThread.Start();
}
}
class Work
{
public static void DoWork()
{
Console.WriteLine("Static thread procedure.");
}
public int Data;
public void DoMoreWork()
{
Console.WriteLine("Instance thread procedure. Data={0}", Data);
}
}
EDIT:
In respect to the type delegate the documentation says:
A delegate is a type that represents references to methods with a particular parameter list and return type.
In this tutorial on MSDN on deleagates you can see how it can be instantiated using the new
keyword:
Instantiating a delegate Once a delegate type has been declared, a delegate object must be created and associated with a particular method. Like all other objects, a new delegate object is created with a new expression.
That means that since Loop
and ThreadStart
have the same return type, namely void
and the same parameter list, (here empty) you can instatiate the delegate using the name of the instance method Loop
.
EDIT 2:
I just was confused about using member function without reference.
This works because you declare the thread in the same class as where the method is declared.
May be there is implicit way of passing
this
reference?
In this context, the answer is yes. If you call a method inside a class or use the name as delegate (pointer to the method) then the this
is implicit.
Upvotes: 8