質問

i have a class (say classA) that contains a string property.

i want to set it to a string property from another class (say classB) so that when i change the property into classA it changes in classB and visa versa.

i know i can do this with functions by using ref but when i try it on my class (Constructor) it doesn't work

here is what i have;

public class myClass 
{
    public string Name;
    public int Image;
    public myClass(ref string myName)
    {
        Name = myName;
    }

    public  void changeIt()
    {
        Name = "xyz";
    }

}

And my main code;

string myString = "abc";
Console.WriteLine("myString:"+myString);
myClass mClass = new myClass(ref myString);
mClass.changeIt();
Console.WriteLine("myString (After doThis):" + myString);
Console.ReadLine();

when i run it it produces;

myString:abc
myString (After doThis):abc

is there something i am missing here? why doesn't it change to xyz?

役に立ちましたか?

解決

Generally speaking, a change in the state of an object should be communicated with an event.

So in the class that has the "important" property, when you change its value an event should be fired.

The other classes should be suscripted to this event and catch it.

You can add the value of the changed string to the fired event so that you won't even need to reference the object when the string value has changed.

You can see how events work in C# on this link.

An example of how to do it can be as follow:

class ClassWithImportantProperty
{
    string myString = string.Empty;

    public string MyImportantProperty
    {
        get { return myString; }
        set
        {
            myString = value;
            if (PropertyChanged != null)
                PropertyChanged(myString, EventArgs.Empty);
        }
    }

    public event EventHandler PropertyChanged;
}

class SecondClass
{
    public string MyDependantString { get; set; }

     public secondClass()
     {
         var classInstance = new ClassWithImportantProperty();
         classInstance.PropertyChanged += classInstance_PropertyChanged;
     }

     void classInstance_PropertyChanged(object sender, EventArgs e)
     {
         MyDependantString = sender.ToString();
     } 
}

Basically you have a class that fires an event every time one of it's properties change. Then another class that is suscribed to this event and every time it gets fired, it does some process of it's own.

他のヒント

Strings are immutable. What this means, is that when you "change" a string.. you're actually throwing away the old one and creating a completely new one. There is no getting around that without using some dodgy unsafe code. ("throwing away" in this context is.. forgetting about it.. allowing it to be cleaned up later by the Garbage Collector).

What this means in the context of your code, is that this:

Name = "xyz";

Creates a new string reference with the content xyz and assigns it to the reference Name. myString in the caller is unaffected by that.. it is a different reference.

As mentioned by @SimonWhitehead, strings are immutable. What you could do in this case, is to change your changeIt method to take an out parameter, and then pass in myString as the input, like so:

public  void changeIt(out string myName)
{
    myName = "xyz";
}

This will give you the output "xyz" after you make a call to this method as:

myClass.changeIt(out myString);

You are referencing a string into the constructor and changing its value in other method. So the ref keyword works only inside a block of code, constructor in this case.

This code will change the value myName to Name. But after constructor is called myName won't be referencing to a Name anymore. Note that you are assigning Name to ref myName and it won't reference to a Name.

public myClass(ref string myName)
{
    myName = Name;
}

This will change the string as well:

public void changeIt(ref string myName)
{
    Name = "xyz";
    myName = Name;
}

I won't write about immutable because other guys already answered. You can do the trick with interfaces like so:

class Program
{
    public interface IName
    {
        string Name { get; }
    }
    public class myClass : IName
    {
        public string Name { get; set; }
        public myClass(string myName)
        {
            Name = myName;
        }
        public void changeIt()
        {
            Name = "xyz";
        }
    }
    public class myClass2 : IName
    {
        private IName iname;
        public string Name { get { return iname.Name; } }
        public myClass2(IName myName)
        {
            iname = myName;
        }
    }
    static void Main(string[] args)
    {
        myClass mClass = new myClass("abc");
        myClass2 m2Class = new myClass2(mClass);

        Console.WriteLine("myString:" + m2Class.Name);

        mClass.changeIt();

        Console.WriteLine("myString (After doThis):" + m2Class.Name);
        Console.ReadLine();
    }
}

It will actually do what you want to achieve. result

To change the string, make the following changes in your code.

 public string changeIt()
 {
     return "xyz"; //return a string from method
 }

In the calling part

 myString=mClass.changeIt(); //assign return value to myString
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top