How to share a variable between two classes? - c#

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

Related

Ambiguous method call without optional parameters

I have a class with two constructors:
public class Foo
{
public Foo(string bar = "hello"){
}
public Foo(string bar = "hello", string barrier = "world"){
}
}
Now, when I want to call the constructor with 1 parameter, I can call:
new Foo();
But I'm getting an ambiguous reference error because Visual Studio doesn't know which constructor I want to use. How can I specify which constructor I want without passing parameters?
To solve the ambiguity, you should make the second method have a required parameter:
public class Foo
{
public Foo(string bar = "hello"){
}
public Foo(string bar, string barrier = "world"){
}
}
That is the only way to make the method resolution deterministic.
But as noted already, that default parameter is useless, since in any other case it will drop to the second constructor. A better option is to drop the first constructor, but if that works out depends on the implementation inside:
public class Foo
{
public Foo(string bar = "hello", string barrier = "world"){
}
}
The point of default values is to reduce the number of methods, just have
public class Foo
{
public Foo(string bar = "hello", string barrier = "world"){
}
}
and set whatever defaults you need for the call, Foo is a single class that should handle all the defaults otherwise its seems it's being used for different purposes
Just make one method that checks both params for string.isNullOrEmpty
static void Main(string[] args)
{
testme("DD", "jj");
Console.ReadLine();
}
public static void testme(string d="", string s = "")
{
if (string.IsNullOrWhiteSpace(d) && string.IsNullOrWhiteSpace(s))
return;
if(string.IsNullOrEmpty(d))
Console.Write(s);
if (string.IsNullOrEmpty(s))
Console.Write(d);
}
It can be solved quite simply like this, using just one constructor. I've added some extra code to faciliate a simple demonstration:
public class Foo
{
private string _bar;
private string _barrier;
public Foo(string bar = "hello", string barrier = "world"){
_bar = bar;
_barrier = barrier;
}
public void show()
{
Console.WriteLine("_bar = " + _bar + " , _barrier = " + _barrier);
}
}
Then all of these combinations are valid...
Foo a = new Foo();
a.show();
Foo b = new Foo("b");
b.show();
Foo c = new Foo(barrier: "c");
c.show();
Foo d = new Foo("d", "e");
d.show();
...and result in the following output:
_bar = hello , _barrier = world
_bar = b , _barrier = world
_bar = hello , _barrier = c
_bar = d , _barrier = e
Maybe you don't need public constructors? Try something like this:
class Program
{
static void Main (string[] args)
{
var person = Person.FromName ();
}
}
public class Person
{
private Person (string name, string surname) { }
public static Person FromName (string name = "John") => new Person (name, "Smith");
public static Person FromFullName (string name = "John", string surname = "Smith") => new Person (name, surname);
}
Of course Person class is just an example (bad example :P) but you should get the idea.

How do I use the propful aspect in Visual studio?

How do I use the propfull tab tab gadget in visual studio?
Class Foo
{
public int regirsterR0
{
get { return R0; }
set { R0 = value; }
}
}
How would I use the get and set methods from another class? Let's say this method is in a class called foo. How would I use the get and set from foo in goo?
Class Goo
{
Foo g= new Foo();
g.regirsterR0.Get?????
}
First, thats called a snippet (and there are a bunch of others!). This one creates a full property (MSDN) definition.
To answer your question; you just use it as if it were a field:
var test = g.Register0; //invokes get
g.Register0 = 2; //invokes set
get and set are nice method abstractions that are called when the associated property is accessed or assigned to.
Note that you don't even need the snippet; you could have used an auto-property:
public int RegisterR0 { get; set; } //Properties are PascalCase!
Get and Set is not a value or method. Actually they are property like a control mechanism. (encapsulation principle)
for ex:
var variable = g.Register0; // so it is get property. // like a var variable = 5;
g.Register0 = 5; // so it is set property.
Look msdn explaining.
You just forgot create method. :-)
class Foo
{
private int regirsterR0;
public int RegirsterR0
{
get { return regirsterR0; }
set { regirsterR0 = value; }
}
}
class Goo
{
Foo g = new Foo();
void myMethod()
{
// Set Property
g.RegirsterR0 = 10;
// Get property
int _myProperty = g.RegirsterR0;
}
}
If you want initialize new object of class Foo with Value you can:
class Foo
{
private int regirsterR0;
public int RegirsterR0
{
get { return regirsterR0; }
set { regirsterR0 = value; }
}
}
class Goo
{
Foo g = new Foo() { RegirsterR0 = 10 };
void myMethod()
{
Console.WriteLine("My Value is: {0}", g.RegirsterR0);
}
}
But usualy you don't need use propfull. Will be fine if you use prop + 2xTAB. Example:
class Foo
{
public int RegirsterR0 { get; set; }
}
class Goo
{
Foo g = new Foo() { RegirsterR0 = 10 };
void myMethod()
{
Console.WriteLine("My Value is: {0}", g.RegirsterR0);
}
}
Wrok the same and easer to read.

How to acess variable value from one class to another class?

I want to access a string from one class to another. I have used the property method as follows -
Myclass.cs
public class MyClass
{
private string _user;
public string user
{ get { return this._user; } set { this._user = value; } }
}
consumption.aspx.cs
I am assigning the value to user in a function
MyClass m = new MyClass();
m.user = "abc"
Now when I try to use this value in my another function which is called after this value is assigned
RawDal.cs
MyClass m = new MyClass();
string x = m.user;
I get empty value... How to do it?
As already mentioned in the comments you are creating two separate instances of MyClass which results simplified in something like:
int a;
a = 3;
int b;
Console.WriteLine("a: " + b); //<-- here it should be obvious why b is not 3
You can work around this in 3 ways:
1) Use the same instance of MyClass for the second call, but in this case you need to be in the same scope or pass the instance on to the new scope.
2) Make the property/member static:
public class MyClass
{
public static string User { get; set; } //the "static" is the important keyword, I just used the alternative property declaration to keep it shorter
}
Then you can access the same User value everywhere via MyClass.User.
3) Use a singleton:
public class MyClass
{
private static MyClass instance = null;
public static MyClass Instance
{
get
{
if(instance == null)
instance = new MyClass();
return instance;
}
}
public string User { get; set; }
}
Then you can access it via MyClass.Instance.User.
There are possibly some more solutions, but these are the common ones.
You are not using the same instance. Try
public class MyClass
{
private string _user;
public string user
{ get { return this._user; } set { this._user = value; } }
}
public string YourFunction()
{
MyClass m = new MyClass();
m.user = "abc"
return m.user;
}
If all you want to return is a string try something like
string x = YourFunction();

Behavior of String in C#

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

Need something like static inheritance in C#

I'm having a small design issue and wanted to consult.
Lets say we have the following class hierarchy:
abstract class A
{
}
class B : A
{
}
class C: A
{
}
I want that both B and C have a certain field x so that it's value is different between the classes but shared among all instances of the same class (i.e: if b1, b2 are instances of B and c1,c2 instances of C then b1.x = b2.x and c1.x = c2.x and b1.x != c1.x).
Is there an elegant way to do this by taking advantage of the fact that both B, C derive from the same base class or do I have to create a static field x in both classes?
Thanks in advance.
You mean like this?
abstract class A
{
static Dictionary<Type, int> all_x;
protected int X {
get { return all_x[GetType()]; }
set { all_x[GetType()] = value; }
}
}
If it has to be a field so you can pass by reference:
abstract class A
{
class SharedType { int x; }
static Dictionary<Type, SharedType> all_shared;
protected SharedType Shared {
get
{
Type t = GetType();
SharedType result;
if (!all_shared.TryGetValue(t, out result) {
result = new SharedType();
all_shared.Add(t, result);
}
return result;
}
}
}
Also, we can improve performance by doing the lookup only once per instance:
abstract class A
{
class SharedType { int x; }
static Dictionary<Type, SharedType> all_shared;
protected SharedType Shared;
A() {
Type t = GetType();
if (!all_shared.TryGetValue(t, out Shared) {
Shared = new SharedType();
all_shared.Add(t, Shared);
}
}
}
What should those values be for the field x? If you need to specify that the value of x for A should be "a", the value of x for B should be "b" etc., then you will have to specify the values "a", "b", ... somewhere and then you mught as well just use:
abstract class A {
public static int x = 1; // Just using "int" as example.
}
class B : A {
public static int x = 2;
}
If you do not care what the values are (which type do you need then) but merely want the values to be "different", then instead of using fields you could use something like:
abstract class A {
public int X { get { return this.GetType().GetHashCode(); } }
}
This does not take hash collisions into account, but maybe it is useful anyway?
What is it you are trying to achieve?
To build on Ben Voigt's first answer, I think what you want for your base class is this:
public abstract class A
{
private static ConcurrentDictionary<Type, int> _typeIDs = new ConcurrentDictionary<Type, int>();
private static int _nextID = 1;
public int TypeID
{
get
{
return _typeIDs.GetOrAdd(this.GetType(), type => System.Threading.Interlocked.Increment(ref _nextID));
}
}
}
public abstract class A
{
public abstract int Value { get; }
}
public class B : A
{
public override int Value { get { return 1; } }
}
public class C : A
{
public override int Value { get { return 2; } }
}
The only way I know to do this is if you make class A a generic class, i.e. class A<T>. Then have class B implement a different type for the generic type than the generic type that Class C implements.
If you don't use generics, then I believe this is impossible in .NET.
Here is an example where lets say the value you were interested in was a data structure with members int Foo and string Bar. One derive class could implement the an identical structure (but different derived type) than the other - the two structures would implement the same interface.
interface IAvalue
{
int Foo { get; set;}
string Bar {get; set;}
}
struct BValue
: IAvalue
{
public int Foo { get; set; }
public string Bar { get; set; }
}
struct CValue
: IAvalue
{
public int Foo { get; set; }
public string Bar { get; set; }
}
abstract class A<T> where T : IAvalue
{
protected static T myValue;
}
class B : A<BValue>
{
static B()
{
myValue.Foo = 1;
myValue.Bar = "text1";
}
}
class C : A<CValue>
{
static C()
{
myValue.Foo = 2;
myValue.Bar = "text2";
}
}
You can use one .net feature: If you have static data members in a generic class, .net creates different instances of static data members for each generic type you use.
So, you can write:
public abstract class A<T> where T : A<T>
{
protected static int myVariable { get; set; }
}
And inherit your classes as:
public class B : A<B>
{
public B()
{
myVariable = 1;
}
public int GetVariable()
{
return myVariable;
}
}
public class C : A<C>
{
public C()
{
myVariable = 2;
}
public int GetVariable()
{
return myVariable;
}
}
Then every instance of B will have shared access to one instance of myVariable and every instance of C will have shared access to another.
So, if you add Set(int a) method:
public void Set(int a)
{
myVariable = a;
}
And run the following code:
static void Main(string[] args)
{
B b1 = new B();
C c1 = new C();
B b2 = new B();
C c2 = new C();
Console.Write("{0}; ", b1.GetVariable()); // 1
Console.Write("{0}; ", b2.GetVariable()); // 1
Console.Write("{0}; ", c1.GetVariable()); // 2
Console.Write("{0}; ", c2.GetVariable()); // 2
Console.WriteLine();
c2.Set(333);
Console.Write("{0}; ", b1.GetVariable()); // 1
Console.Write("{0}; ", b2.GetVariable()); // 1
Console.Write("{0}; ", c1.GetVariable()); // 333
Console.Write("{0}; ", c2.GetVariable()); // 333
Console.ReadLine();
}
You get: 1; 1; 2; 2;
1; 1; 333; 333; output.
I would suggest defining a static Dictionary<Type, Integer[]>, and having the base-class constructor call GetType() on itself and see if it's yet in the static dictionary. If not, create a new single-element array and store it in the dictionary. Otherwise grab the array from the dictionary and store it in an instance field. Then define a property which reads or writes element zero of the array. This approach will achieve the requested semantics for all derivatives and sub-derivatives of the class.

Categories

Resources