Is there any way to create a non-static thread method at .NET?
Show me code please.
The following code doesn't work:
ThreadStart ts = delegate { drawFloorAround(); };
public void drawFloorAround()
{
...
}
Gives this error -> "A field initializer cannot reference the non-static field, method, or property".
If I change the method do static, it works. But I don't want to.
... gives this error "A field initializer cannot reference the non-static field, method, or property".
Read the error message more carefully. It is telling you precisely what is wrong. A field initializer cannot reference a non-static method. That's because the compiler is trying to protect you from this bug:
class C
{
int foo;
int bar = GetBar();
public C(int newFoo)
{
this.foo = newFoo;
}
private int GetBar() { return this.foo + 1; }
}
You do "new C(123)". What is bar set to? If this were legal code then it would be set to 1, not 124. Why? Because first foo gets initialized to zero, then GetBar() gets called, then the constructor body sets this.foo to 123.
To prevent this bug it is simply illegal to reference an instance method or field in a field initializer.
Now, you might reasonably point out that in your code, you do not use the instance method, you only reference it. You never actually call it. This actually is safe. However, the rules of C# are designed to be simple and conservative; even though we could prove that this case is safe, we take the conservative, simple path and say that any reference to the instance in a field initializer is illegal.
If I change the method to static, it works.
Correct. In that case, the method does not depend upon instance state which has not yet been set up.
But I don't want to.
OK, then your only other choice is to stop using a field initializer. Put the initialization in the constructor; you then take responsibility for ensuring that the initialization does not accidentally use uninitialized state.
If you mean is it possible to start a thread with a non-static method - i.e. an instance method - then yes it is. But the same rules apply as to calling an instance method directly - you can only do it if you have an instance. For example, if you have an instance in a variable called foo then you can write this:
ThreadStart ts = delegate { foo.DrawFloorAround(); };
If you don't already have an instance that you can use, then you must first create one:
ThreadStart ts = delegate { new Foo().DrawFloorAround(); };
If you don't want to create an instance then your method probably should be static.
Yes
public class DoSomthing
{
public void Do()
{
Thread t = new Thread(DoInBackground);
t.Start();
}
public void DoInBackground()
{
// ....
}
}
Edit: the problem in the example code is that it is a field initialiser. Move this code to an explicit constructor:
ThreadStart ts;
public TypeName() {//constructor
ts = this.SomeMethod;
}
private void SomeMethod() {....}
Any method can act as a ThreadStart as log ad it takes no args and returns void. IMO the easiest option is a lambda or anon method as this allows closures:
ThreadStart ts = delegate {
someObj.DoSomething(x, y, "z");
};
But for an instance method that returns void and takes no args:
var obj = /* init obj */
ThreadStart ts = obj.SomeMethod;
Then
var thread = new Thread(ts);
Initializers run before constructors, so you have no instance to set it to. Set the value in your constructor and you should be okay.
class DoesNotWork {
public Action ts = Frob; // doesn't work, cannot access non-static method
void Frob() { }
}
class ThisIsFine {
public Action ts;
public ThisIsFine() { ts = Frob; }
void Frob();
}
It's important for anyone moving to C# from vb.net to note that the rules have changed between VB.net and C#. Under the vb.net (IMHO better) rules, initializers run between the call to mybase.new and the following statement of the constructor; it is permissible for field initializers to make reference to fields and properties of the current object. While this can cause problems if done carelessly, it allows variable initialization (and in some cases cleanup) to be handled at the same place in source code as the declaration. Anyone migrating to C# needs to recognize this difference in initializer handling. While it's possible in vb.net to properly dispose an iDisposable which is created in an initializer, that is not possible in C# without a severe kludge using a threadstatic variable.
Related
If I am passing an object to a method, why should I use the ref keyword? Isn't this the default behaviour anyway?
For example:
class Program
{
static void Main(string[] args)
{
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(t);
Console.WriteLine(t.Something);
}
static public void DoSomething(TestRef t)
{
t.Something = "Bar";
}
}
public class TestRef
{
public string Something { get; set; }
}
The output is "Bar" which means that the object was passed as a reference.
Pass a ref if you want to change what the object is:
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(ref t);
void DoSomething(ref TestRef t)
{
t = new TestRef();
t.Something = "Not just a changed t, but a completely different TestRef object";
}
After calling DoSomething, t does not refer to the original new TestRef, but refers to a completely different object.
This may be useful too if you want to change the value of an immutable object, e.g. a string. You cannot change the value of a string once it has been created. But by using a ref, you could create a function that changes the string for another one that has a different value.
It is not a good idea to use ref unless it is needed. Using ref gives the method freedom to change the argument for something else, callers of the method will need to be coded to ensure they handle this possibility.
Also, when the parameter type is an object, then object variables always act as references to the object. This means that when the ref keyword is used you've got a reference to a reference. This allows you to do things as described in the example given above. But, when the parameter type is a primitive value (e.g. int), then if this parameter is assigned to within the method, the value of the argument that was passed in will be changed after the method returns:
int x = 1;
Change(ref x);
Debug.Assert(x == 5);
WillNotChange(x);
Debug.Assert(x == 5); // Note: x doesn't become 10
void Change(ref int x)
{
x = 5;
}
void WillNotChange(int x)
{
x = 10;
}
You need to distinguish between "passing a reference by value", and "passing a parameter/argument by reference".
I've written a reasonably long article on the subject to avoid having to write carefully each time this comes up on newsgroups
In .NET when you pass any parameter to a method, a copy is created. In value types means that any modification you make to the value is at the method scope, and is lost when you exit the method.
When passing a Reference Type, a copy is also made, but it is a copy of a reference, i.e. now you have TWO references in memory to the same object. So, if you use the reference to modify the object, it gets modified. But if you modify the reference itself - we must remember it is a copy - then any changes are also lost upon exiting the method.
As people have said before, an assignment is a modification of the reference, thus is lost:
public void Method1(object obj) {
obj = new Object();
}
public void Method2(object obj) {
obj = _privateObject;
}
The methods above does not modifies the original object.
A little modification of your example
using System;
class Program
{
static void Main(string[] args)
{
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(t);
Console.WriteLine(t.Something);
}
static public void DoSomething(TestRef t)
{
t = new TestRef();
t.Something = "Bar";
}
}
public class TestRef
{
private string s;
public string Something
{
get {return s;}
set { s = value; }
}
}
Since TestRef is a class (which are reference objects), you can change the contents inside t without passing it as a ref. However, if you pass t as a ref, TestRef can change what the original t refers to. i.e. make it point to a different object.
With ref you can write:
static public void DoSomething(ref TestRef t)
{
t = new TestRef();
}
And t will be changed after the method has completed.
Think of variables (e.g. foo) of reference types (e.g. List<T>) as holding object identifiers of the form "Object #24601". Suppose the statement foo = new List<int> {1,5,7,9}; causes foo to hold "Object #24601" (a list with four items). Then calling foo.Length will ask Object #24601 for its length, and it will respond 4, so foo.Length will equal 4.
If foo is passed to a method without using ref, that method might make changes to Object #24601. As a consequence of such changes, foo.Length might no longer equal 4. The method itself, however, will be unable to change foo, which will continue to hold "Object #24601".
Passing foo as a ref parameter will allow the called method to make changes not just to Object #24601, but also to foo itself. The method might create a new Object #8675309 and store a reference to that in foo. If it does so, foo would no longer hold "Object #24601", but instead "Object #8675309".
In practice, reference-type variables don't hold strings of the form "Object #8675309"; they don't even hold anything that can be meaningfully converted into a number. Even though each reference-type variable will hold some bit pattern, there is no fixed relationship between the bit patterns stored in such variables and the objects they identify. There is no way code could extract information from an object or a reference to it, and later determine whether another reference identified the same object, unless the code either held or knew of a reference that identified the original object.
This is like passing a pointer to a pointer in C. In .NET this will allow you to change what the original T refers to, personally though I think if you are doing that in .NET you have probably got a design issue!
By using the ref keyword with reference types you are effectively passing a reference to the reference. In many ways it's the same as using the out keyword but with the minor difference that there's no guarantee that the method will actually assign anything to the ref'ed parameter.
ref mimics (or behaves) as a global area just for two scopes:
Caller
Callee.
If you're passing a value, however, things are different. You can force a value to be passed by reference. This allows you to pass an integer to a method, for example, and have the method modify the integer on your behalf.
If I am passing an object to a method, why should I use the ref keyword? Isn't this the default behaviour anyway?
For example:
class Program
{
static void Main(string[] args)
{
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(t);
Console.WriteLine(t.Something);
}
static public void DoSomething(TestRef t)
{
t.Something = "Bar";
}
}
public class TestRef
{
public string Something { get; set; }
}
The output is "Bar" which means that the object was passed as a reference.
Pass a ref if you want to change what the object is:
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(ref t);
void DoSomething(ref TestRef t)
{
t = new TestRef();
t.Something = "Not just a changed t, but a completely different TestRef object";
}
After calling DoSomething, t does not refer to the original new TestRef, but refers to a completely different object.
This may be useful too if you want to change the value of an immutable object, e.g. a string. You cannot change the value of a string once it has been created. But by using a ref, you could create a function that changes the string for another one that has a different value.
It is not a good idea to use ref unless it is needed. Using ref gives the method freedom to change the argument for something else, callers of the method will need to be coded to ensure they handle this possibility.
Also, when the parameter type is an object, then object variables always act as references to the object. This means that when the ref keyword is used you've got a reference to a reference. This allows you to do things as described in the example given above. But, when the parameter type is a primitive value (e.g. int), then if this parameter is assigned to within the method, the value of the argument that was passed in will be changed after the method returns:
int x = 1;
Change(ref x);
Debug.Assert(x == 5);
WillNotChange(x);
Debug.Assert(x == 5); // Note: x doesn't become 10
void Change(ref int x)
{
x = 5;
}
void WillNotChange(int x)
{
x = 10;
}
You need to distinguish between "passing a reference by value", and "passing a parameter/argument by reference".
I've written a reasonably long article on the subject to avoid having to write carefully each time this comes up on newsgroups
In .NET when you pass any parameter to a method, a copy is created. In value types means that any modification you make to the value is at the method scope, and is lost when you exit the method.
When passing a Reference Type, a copy is also made, but it is a copy of a reference, i.e. now you have TWO references in memory to the same object. So, if you use the reference to modify the object, it gets modified. But if you modify the reference itself - we must remember it is a copy - then any changes are also lost upon exiting the method.
As people have said before, an assignment is a modification of the reference, thus is lost:
public void Method1(object obj) {
obj = new Object();
}
public void Method2(object obj) {
obj = _privateObject;
}
The methods above does not modifies the original object.
A little modification of your example
using System;
class Program
{
static void Main(string[] args)
{
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(t);
Console.WriteLine(t.Something);
}
static public void DoSomething(TestRef t)
{
t = new TestRef();
t.Something = "Bar";
}
}
public class TestRef
{
private string s;
public string Something
{
get {return s;}
set { s = value; }
}
}
Since TestRef is a class (which are reference objects), you can change the contents inside t without passing it as a ref. However, if you pass t as a ref, TestRef can change what the original t refers to. i.e. make it point to a different object.
With ref you can write:
static public void DoSomething(ref TestRef t)
{
t = new TestRef();
}
And t will be changed after the method has completed.
Think of variables (e.g. foo) of reference types (e.g. List<T>) as holding object identifiers of the form "Object #24601". Suppose the statement foo = new List<int> {1,5,7,9}; causes foo to hold "Object #24601" (a list with four items). Then calling foo.Length will ask Object #24601 for its length, and it will respond 4, so foo.Length will equal 4.
If foo is passed to a method without using ref, that method might make changes to Object #24601. As a consequence of such changes, foo.Length might no longer equal 4. The method itself, however, will be unable to change foo, which will continue to hold "Object #24601".
Passing foo as a ref parameter will allow the called method to make changes not just to Object #24601, but also to foo itself. The method might create a new Object #8675309 and store a reference to that in foo. If it does so, foo would no longer hold "Object #24601", but instead "Object #8675309".
In practice, reference-type variables don't hold strings of the form "Object #8675309"; they don't even hold anything that can be meaningfully converted into a number. Even though each reference-type variable will hold some bit pattern, there is no fixed relationship between the bit patterns stored in such variables and the objects they identify. There is no way code could extract information from an object or a reference to it, and later determine whether another reference identified the same object, unless the code either held or knew of a reference that identified the original object.
This is like passing a pointer to a pointer in C. In .NET this will allow you to change what the original T refers to, personally though I think if you are doing that in .NET you have probably got a design issue!
By using the ref keyword with reference types you are effectively passing a reference to the reference. In many ways it's the same as using the out keyword but with the minor difference that there's no guarantee that the method will actually assign anything to the ref'ed parameter.
ref mimics (or behaves) as a global area just for two scopes:
Caller
Callee.
If you're passing a value, however, things are different. You can force a value to be passed by reference. This allows you to pass an integer to a method, for example, and have the method modify the integer on your behalf.
Since I am writing a generic concept for some action to be perform, I need to call some non static method in the Action delegate. Also, none of them are static in my code. But still I can't call the non static method inside the Action definition.
Here's my code-
private Dictionary<string, Action<object>> m_dicUndoRedoAction = new Dictionary<string, Action<object>>();
m_dicUndoRedoAction.Add("DeleteClass", DeleteClassFromeNode );
and Here's the definition of DeleteClass
private Action<object> DeleteClassFromeNode =
data =>
{
Tuple<itemType1, itemType2> items = data as Tuple<itemType1, itemType2>;
if (items != null && items.Item2 != null)
{
DeleteClass(items.Item2); // This is my non static method in the same class.
}
};
and Here's how I call the delegate
private void Undo_Executed(object sender, ExecutedRoutedEventArgs e)
{
object temp;
if (UndoRedoAction.DoUndo(out temp))
{
m_dicUndoRedoAction["DeleteClass"].Invoke(temp);
}
}
as compiler says
A field initializer cannot reference the non-static field, method, or
property 'DeleteClassFromeNode'
I have also reviewed MSDN reference for Action article, but nowhere MS has mentioned whether, Action is implicitly static, or am I going some wrong way ?
I also looked up on some nonstatic call from static methods, but none of them were satisfactory explained.
I would appreciate it if anyone provide its low level explanation.
On response to Peter explanation
Though initializers run before the constructor has completed, that doesn't make it to trigger the delegate in between the constructor execution. Even if you will look up its assembly code in ILDASM, it shows the real action Field as non static, but cached anonymous delegate object as static. Why this different behavior by compiler ?
Just as the compiler is telling you, you are prohibited from using non-static members in an initializer. This is because initializers run before the constructor has completed, and so it is not necessarily safe to use non-static members.
Instead, just perform the initialization in the constructor:
public MyClass()
{
DeleteClassFromeNode = data =>
{
Tuple<itemType1, itemType2> items = data as Tuple<itemType1, itemType2>;
if (items != null && items.Item2 != null)
{
DeleteClass(items.Item2); // This is my non static method in the same class.
}
};
// Other initialization code can go here (or before...whatever is most appropriate)
}
EDIT : Sorry. It seems I got a little confused. I was attempting to call a non-static method within a static method, and it wasn't working. They were in the same class. That led me to (incorrectly) assume that I cannot call a non-static without instantiation, even though they belong to the same class.
Since I already created the question, allow me to change the question a little. Why can I not call a non-static method within a static one? Here's my code so that you can tell me if I'm just screwing myself over with something silly:
public class DataAccessObjectClass
{
public static IList<Records> GetAllRecords(Dictionary<string,string> searchDic)
{
string query = BuildSearchQuery(searchDic); //error: object ref. required
}
public string BuildSearchQuery(Dictionary<string,string> searchDic)
{
string query = "";
//build the query
return string;
}
}
Is it something in the System.Web.UI.Page class?
No, It is because you're already inside the instance method. There is an implicit instance this which already exist in the context, this instance will be used to call that method.
There is nothing special with Page class, in any class you can do the same, You can call whatever instance method from another instance method without an instance(although you're technically using this as implicit reference).
You don't need to instantiate the class because it's already been instantiated for you.
Consider the class
public class C
{
public void f() { g(); }
public void g() { }
}
Now, you cannot simply call C.g();, you need an instance to call it on. new C().g(); would work, but so would
var c = new C();
c.g();
The call from f to g already has an instance to call g on, which is this. There, g(); simply means this.g();. c.f(); would end up calling c.g() from within f.
For your edited question, consider this class:
public class D
{
public static void f() { g(); } // error
public void g() { }
}
Now, because D.f is static, you could call it as simply D.f();. In that case, there isn't any instance of D at all yet, so you have no instance to call g on. (Or, if you do create instances of D first, the system wouldn't know which of those instances to call g on.)
Actually, Page_Load is beeing called when the page is rendered, so, there is an instantiate of the class DefaultPage, and this object is the one that is calling to Page_Load and to GetObjects.
I notice that if you have a private member in a class, you can access it in the class methods by just referring to it's name. You do not need to say this.memberName, just memberName works. So is the this keyword optional in the context of member access?
I do see it is useful when you want to clarify the scope - when you have 2 variables with the same name. Is there any other reason to use it when accessing members?
Yes, it's optional. The only times you'd have to use it are when you have a local variable that hides a member variable, or you want to refer to an indexed property (aka indexer).
You can optionally use this in instance member access from within an instance members like an instance method or property because whenever an instance method is called this (referring to the current object) is automatically passed in as an invisible parameter.
You cannot use this from within static members to access instance member... like you cannot use this.x or this.y (or even simple x and y) from within a static method or property if x and y are instance members. This is because this is undefined in a static member call. The static member belongs to the whole class... it has no idea which instance this is referring to. And that is due to the fact that when you call a static method or property , the call is of the format ClassName.MethodName(); So the static method does not know what object this will refer.
this is also not optional (it must be used) as the first modifier in the parameter list of an extension method. In fact this is what identifies a static method as an extension method. Here now this identifies the first parameter as the instance on which the extension method is working.
using System;
class Class_name
{
static string static_variable="static";
string instance_variable="instance";
static void Main()
{
Class_name object_name = new Class_name();
Console.WriteLine("Printing out instance and static variables from within Main() body :");
Console.WriteLine(object_name.instance_variable);
Console.WriteLine(Class_name.static_variable);
/* Note that we cannot say either of the following :
object_name.static_variable
Class_name.instance_variable
*/
Console.WriteLine();
// now lets call the static and instance methods
object_name.Instance_method(); // Now this is the key call which
// passes "this" as an invisible parameter
// to the Instance_method. "this" refers to
// object_name
Class_name.Static_method();// "this" is NOT passed to Static_method() because now
// the call is made on Class_name ... so there is nothing
// to be represented by "this"
Console.ReadLine();
}
void Instance_method()
{
// here we receive "this" as an invisible parameter referring
// to the object on which Instance_method is called (i.e. object_name)...
// ... see the Main() method for comments at the call site.
Console.Write("Instace method called ... " +
"prints out instance variable twice, with and without 'this': ");
// the following two calls mean exactly the same.
Console.Write(this.instance_variable);
Console.WriteLine (instance_variable);
// one little additional point is that static members are
// accessible from within instance members
Console.WriteLine();
Console.Write("static variables can also be accessed from within Instance_method: ");
Console.WriteLine(static_variable);
Console.WriteLine();
Console.WriteLine();
}
static void Static_method()
{
// See the Main() method body for the call Class_name.Static_method()
// Notice that this method is called on Class_name and not object_name
// which means that there is no invisibly passed-in "this" parameter available
// in this method.
// we can also not access the instance_variable in this method
// as instance variables are always part of some object. This method
// is not called on any object, its called on Class_name.
// Console.WriteLine(instance_variable); // Compiler error
Console.WriteLine("Static method called ... prints out static variable: ");
Console.WriteLine(static_variable);
}
}
Yes, 'this' is implied. It can sometimes help for clarity. And it is also necessary for calling methods and need to reference the current class.
"This" is almost always optional when you call members of current class.
However, it is used for other purposes, e.g. to pass the current class instance as a parameter or to set a property,field or variable to the current instance.
The only case where you must use it to call a method is when you call an extension method:
class AClass {
void CallIt() {
Test(); //not valid
this.Test(); //valid
}
}
static class AnExtension {
public static void Test(this AClass source) {
}
}