Greetings everyone
I was wondering if i have bool x = true; and i call a method after that might change x value. would this change apply if the method is void & don't return the result. Example :
bool x = true;
string x = "";
Change_value(x);
if (!(x))
x = "Ok";
would x value change when i call my method or do i need to do it as x = change_value(x)
This depends on the type of the variable you are passing to a method. In your example no.
Value types will not see changes reflected in the calling scope, where properties on reference values will.
This answer explains the concept well
Note that you can use the ref keyword to have value types updated like reference types also.
You can change members of reference values, but you cannot reassign
them.
namespace ConsoleApplication1
{
public class TestObj
{
public string Val { get; set; }
}
class Program
{
static void Main(string[] args)
{
var testObj = new TestObj { Val = "Initial instance" };
Console.WriteLine(testObj.Val);
AssignNewInstance(testObj);
Console.WriteLine(testObj.Val);
// Prints:
// 'Initial instance'
// 'Changed in AssignNewInstance'
// 'Initial instance'
}
public static void AssignNewInstance(TestObj testObj)
{
testObj = new TestObj { Val = "Changed in AssignNewInstance" };
Console.WriteLine(testObj.Val);
}
}
}`
I think what you might be looking for is passing a value type (bool) by reference. You can do this using the ref keyword. Here is the relevant excerpt:
The ref keyword causes an argument to be passed by reference, not by value. The effect of passing by reference is that any change to the parameter in the called method is reflected in the calling method.
So, it should change the variable if you change your code to this (add the "ref"):
bool x = true;
string x = "";
Change_value(ref x);
if (!(x))
x = "Ok";
And then the Change_value would be declared like this:
void Change_value(ref bool someBool) { //do whatever }
bool is a primitive, so it's passed by value (a copy passed to change_value).
If you want to change it's value in the method you can use the Boolean class, like that:
Boolean x = true;
string x = "";
Change_value(ref x);
if (!(x))
x = "Ok";
you have to use the ref prefix in the method parameters
void Change_value(ref Boolean x)
{
...
}
and call it like this:
Change_value(ref x);
you can go for MS explain: https://msdn.microsoft.com/en-us/library/14akc2c7.aspx
Unless you pass value X by reference the value of x should not change.
You can define b as a field inside your class. Once you did that, you just have to assign it and the new value will be available from that moment on.
Here is a short example:
public static class Program
{
private static bool b;
public static void Main()
{
b = true;
Console.WriteLine(b);
DoStuff();
Console.WriteLine(b);
}
private static void DoStuff()
{
b = false;
}
}
This way you can access and modify b from anywhere inside your class.
Related
I am running into a road block when I am trying to do some testing on delegate. My goal is to create instances of MyStates class that have the ability to call some predefined functions that I defined in MyFunctions class. In the class, I have a dictionary that will refer the functions by name and have a function that retrieve the address of the function and put it in MyState instance so that I could refer it at run time. The idea appears to be simple but the compiler is not happy about it. I think I may have an idea of what is wrong but I am not sure how to get rid of the compiler error. Please advise how to fix this compiler error.
MyFunctions class is defined as below:
public sealed class MyFunctions
{
public delegate int myFunction(object o);
private static Dictionary<string, myFunction> funcRouter
= new Dictionary<string, myFunction>();
#region Singleton
private static readonly MyFunctions _functionInstance = new MyFunctions();
static MyFunctions()
{
}
private MyFunctions()
{
funcRouter.Add("Test2", Test2);
}
public static MyFunctions functionInstance
{
get
{
return _functionInstance;
}
}
#endregion
#region Definition and implementation of all the functions
public int Test2(object o)
{
System.Diagnostics.Debug.WriteLine("Testing 2, object received {0}", (int)o);
return 112;
}
#endregion
public myFunction Get(string s)
{
return (myFunction)funcRouter[s];
}
}
MyStates class is defined below:
public delegate int myFunction(object o);
public class MyState
{
private int _ID;
private myFunction _func;
public myFunction func
{
get { return _func; }
}
public int ID
{
get { return _ID; }
}
public MyState(int myID, myFunction f = null)
{
_ID = myID;
_func = f;
}
}
My main program:
public delegate int myFunction(object o);
class Program
{
static void Main(string[] args)
{
myFunction f = null;
//f = MyFunctions.functionInstance.Test2;
f = MyFunctions.functionInstance.Get("Test2");
MyState s = new MyState(123,f);
Console.ReadLine();
}
}
Note: The code above will generate the compiling error. However, if I use the statement
f = MyFunctions.functionInstance.Test2;
The program will compile fine and execute correctly. I think the issue resides in the use of dictionary to retrieve the address of the function. It is possible to possible to do that in C++, I would think C# should allow me to do the same thing. I just did not do it correctly.
Please advise.
You are defining public delegate int myFunction(object o); in two places. The compiler error error says you can't convert one to the other. This is because in the case of f = MyFunctions.functionInstance.Get("Test2"); you are assigning a return value of one type to a variable of a different type, but with f = MyFunctions.functionInstance.Test2; the compiler just looks for a method signature that matches the delegate.
One fix is to declare f as MyDelegates.MyFunctions.myFunction.
MyDelegates.MyFunctions.myFunction f;
f = MyDelegates.MyFunctions.functionInstance.Get("Test2");
Another way is to wrap it in your local delegate (because then the signature-match is used again):
myFunction f;
f = new myFunction(MyDelegates.MyFunctions.functionInstance.Get("Test2"));
The same applies to using it in the MyState-call later.
Another way to work around this is to just use Func<object, int> everywhere instead of the myFunction delegate.
public void main()
{
string test = "testing";
ChangeVal(test);
Console.WriteLine(test);
}
private void ChangeVal(string test)
{
test = "in child";
}
If String is a class.
and i pass string as a parameter to a function. change the value of that string in function.
But in main function it shows the previous values. It will print testing value.
when i created Foo class which has 2 member variable integer and string.
when i passed the object of the class as parameter and change value of the member variable in function.
It will give updated value in the main function
public class Foo
{
public string test = "testing";
public int i = 5;
}
public void main()
{
Foo obj=new Foo();
Console.WriteLine(obj.test);
ChangeVal(obj);
Console.WriteLine(obj.test);
}
private void ChangeVal(Foo obj)
{
obj.test = "in child";
obj.i = 5;
}
If string is the class. It will update the value of the variable.
May string is the sequence of Unicode character that's why it doesn't update the value in 1st case.
Can any body will explain this in detail.
change the value of that string in function
Strings are immutable. You can't change the value of a string. You can assign another string to the same reference, but you would need to pass the reference in by using ref.
public void main()
{
string test = "testing";
ChangeVal(ref test);
Console.WriteLine(test);
}
private void ChangeVal(ref string test)
{
test = "in child";
}
You Foo class, however, is mutable, so you can assign different values to its members.
Try to pass the parameter by reference to get the var updated in main thread:
private void SeString(ref string chain)
{
chain="new string";
}
Then call:
string variable="hello";
SeString(ref variable);
string output is "new string"
I have created the fallowing Sample-Code:
class Program {
static void Main(string[] args) {
var x = new ActionTestClass();
x.ActionTest();
var y = x.Act.Target;
}
}
public class ActionTestClass {
public Action Act;
public void ActionTest() {
this.Act = new Action(this.ActionMethod);
}
private void ActionMethod() {
MessageBox.Show("This is a test.");
}
}
When I do this on this way, y will an object of type ActionTestClass (which is created for x). Now, when I change the line
this.Act = new Action(this.ActionMethod);
to
this.Act = new Action(() => MessageBox.Show("This is a test."));
y (the Target of the Action) will be null. Is there a way, that I can get the Target (in the sample the ActionTestClass-object) also on the way I use an Anonymous Action?
The lack of Target (iow == null) implies the delegate is either calling a static method or no environment has been captured (iow not a closure, just a 'function pointer').
the reason why you see the target as empty is because the anonymous method is not part of any class. If you open your program in reflector, it will show you the code that is generated by the compiler, here you will see the following
public void ActionTest()
{
this.Act = delegate {
Console.WriteLine("This is a test.");
};
}
You can use the following:
Act.Method.DeclaringType
I am a C++ programmer, now working on a C# project.
I am trying to understand in the below snippet why the value of string does not change even though the function is changing its value, I thought it is an object and would be passed as a reference.
public class TestClass
{
public TestClass(String passedStr)
{
passedStr = "Change me";
}
}
class Program
{
static void Main(string[] args)
{
String aString="I am what i am";
TestClass obj = new TestClass(aString);
Console.WriteLine(aString);
}
}
But behavior with user defined classes are different.
public class TestClass
{
private int x;
public int ID
{
get
{
return x;
}
set
{
x = value;
}
}
public TestClass(int a)
{
x = a;
}
}
public class Tester
{
public Tester(TestClass obj)
{
obj.ID = 999;
}
}
class Program
{
static void Main(string[] args)
{
TestClass obj = new TestClass(555);
Tester tester = new Tester(obj);
Console.WriteLine(obj.ID);
}
}
Let's go back to basics.
A variable is a storage location.
A variable of type string is a storage location that stores either null, or a reference to a string.
"passedStr" and "aString" are different variables.
When you call "new TestClass(aString)" you create a new storage location for "passedStr" and copy the contents of "aString" into it. You now have two variables that have the same content: a reference to a string.
Inside the constructor you change the value stored in the storage location for "passedStr". "aString" remains the same.
The "ref" and "out" keywords in C# mean "make the formal parameter and the argument aliases of each other". In that case you have only one variable with two different names. When you change one of them the other one changes as well, because they are the same variable.
No, it's passed by value; there's no ref keyword.
It's passing a reference type (here, a class) by value (no ref keyword), just like passing a copy of a pointer in C++. You're reassigning the pointer, not the actual data (which you can't do with strings anyway).
If you need pass-by-reference, try:
public TestClass(ref String passedStr)
{
passedStr = "Change me";
}
...
TestClass obj = new TestClass(ref aString);
Strings are passed by reference but the pointer is passed by value in C#. If you want to pass the string by reference you'll have to make use of the ref key word.
For example:
public class TestClass
{
public TestClass(ref string passedStr)
{
passedStr = "Change me";
}
}
class Program
{
static void Main(string[] args)
{
string aString="I am what i am";
TestClass obj = new TestClass(ref aString);
Console.WriteLine(aString); // "Change me"
}
}
passedStr is not the string, but a constructor parameter that holds a reference to the string. All your TestClass constructor is doing is changing the string that this parameter references. It has no effect outside the constructor.
What you are doing in the constructor, is that you are assigning a new String literal to the local variable passedStr.
In C, the equivalent function would look something like this:
Testclass constructor_testclass(char* passedStr) {
passedStr = "Change me";
}
I think it's obvious that this function does not change the value of the char* in the calling function.
The object I am what i am is being passed by reference, but the reassignment is to a local variable. You don't change the original object, but instead assign a new object (Change me) to the location of the argument.
public class Employee
{
public string ID { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format("ID = {0} Name = {1}", ID, Name);
}
}
public class TestClass2
{
public TestClass2(Employee e)
{
e.ID="007";
e.Name="james";
}
}
static void Main()
{
Employee e = new Employee();
e.ID = "0";
e.Name = "nobody";
TestClass2 t = new TestClass2(e);
Console.WriteLine(e); //Output ID = 007 Name = James
}
strings are passed by reference but the pointer is passed by value in C#
Parameter passing in C# by Jon Skeet
How would you share the same object between two other objects? For instance, I'd like something in that flavor:
class A
{
private string foo_; // It could be any other class/struct too (Vector3, Matrix...)
public A (string shared)
{
this.foo_ = shared;
}
public void Bar()
{
this.foo_ = "changed";
}
}
...
// inside main
string str = "test";
A a = new A(str);
Console.WriteLine(str); // "test"
a.Bar();
Console.WriteLine(str); // I get "test" instead of "changed"... :(
Here, I don't want to give a ref to the Bar method. What I want to achieve is something that would look like that in C++:
class A
{
int* i;
public:
A(int* val);
};
A::A (int* val)
{
this->i = val;
}
I read there is some ref/out stuff, but I couldn't get what I'm asking here. I could only apply some changes in the methods scope where I was using ref/out arguments...
I also read we could use pointers, but is there no other way to do it?
This has nothing to do with sharing objects. You passed a reference to a string into the A constructor. That reference was copied into the private member foo_. Later, you called B(), which changed foo_ to "changed".
At no time did you modify str. str is a local variable in main. You never passed a reference to it.
If you had wanted to change str, you could have defined B as
public void Bar(ref string s)
{
this.foo_ = "changed";
s = this.foo_;
}
Consider:
public class C
{
public int Property {get;set;}
}
public class A
{
private C _c;
public A(C c){_c = c;}
public void ChangeC(int n) {_c.Property = n;}
}
public class B
{
private C _c;
public B(C c){_c = c;}
public void ChangeC(int n) {_c.Property = n;}
}
in main:
C myC = new C() {Property = 1;}
A myA = new A(myC);
B myB = new B(myC);
int i1 = myC.Property; // 1
myA.ChangeC(2);
int i2 = myC.Property; // 2
myB.ChangeC(3);
int i3 = myC.Property; // 3
Wrap your string inside a class. You need to do this because strings are immutable. Any attempt to change a string actually results in a new string.
class Foo {
class StringHolder {
public string Value { get; set; }
}
private StringHolder holder = new StringHolder();
public string Value {
get { return holder.Value; }
set { holder.Value = value; }
}
public Foo() { }
// this constructor creates a "linked" Foo
public Foo(Foo other) { this.holder = other.holder; }
}
// .. later ...
Foo a = new Foo { Value = "moose" };
Foo b = new Foo(a); // link b to a
b.Value = "elk";
// now a.Value also == "elk"
a.Value = "deer";
// now b.Value also == "deer"
I would split my answer to 2 parts:
1) If the variable is a reference type than it is already shared since you pass its reference to all interested objects. The only thing you should pay attention is that the reference type instances are mutable.
2) If the variable is a value type than you would have to use ref or out or some wrapper that is mutable and you can change the value inside the wrapper using a method or a property.
Hope that helps.
You need to pass the paramter as a reference to your method,
class A
{
private string foo_; // It could be any other class/struct too (Vector3, Matrix...)
public A(string shared)
{
this.foo_ = shared;
}
public void Bar(ref string myString)
{
myString = "changed";
}
}
static void Main()
{
string str = "test";
A a = new A(str);
Console.WriteLine(str); // "test"
a.Bar(ref str);
Console.WriteLine(str);
}
When a variable is a string, it is a reference.
Try to clone the string. http://msdn.microsoft.com/en-us/library/system.string.clone.aspx