I can't figure out why MessageBox show "false" if nuovo.matrice refers to the same object but not maintain the array reassignment done by the method. Why nuovo.matrice == mat is false if they refers to the same object?
namespace WindowsFormsApplication15
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
class Class1
{
public ClassType[] matrice;
public class ClassType
{
public string a { get; set; }
public int b { get; set; }
}
}
Class1.ClassType[] mat;
private void Form1_Load(object sender, EventArgs e)
{
Class1 test = new Class1();
Class1.ClassType prova = new Class1.ClassType();
test.matrice = new Class1.ClassType[1];
test.matrice[0] = prova;
mat = test.matrice;
mat[0].a = "rtuier";
mat[0].b = 94;
Modify nuovo = new Modify(mat);
nuovo.inizia();
MessageBox.Show((nuovo.matrice == mat).ToString());
}
class Modify
{
public Class1.ClassType[] matrice;
public Modify(Class1.ClassType[] mat)
{
matrice = mat;
}
public void inizia()
{
matrice[0].a = "asuidh";
matrice[0].b = 123;
Class1.ClassType[] newMatrice = new Class1.ClassType[2];
Class1.ClassType ins = new Class1.ClassType { a = "pollo", b = 456 };
newMatrice[0] = matrice[0];
newMatrice[1] = ins;
matrice = newMatrice;
}
}
}
}
The problem is, they don't ref the same object.. because you cannot alter the mat variable in the class. You get a copy of a reference and you're altering the copy. If you want to be able to modify a reference, you should wrap it in a class. Then you'll get a copy of the wrapper reference, but the Class1 field is unique.
Class wrap example:
public class ClassType
{
public string a { get; set; }
public int b { get; set; }
}
public class Class1
{
public ClassType[] classType;
}
public class Wrapper
{
public Class1 WrappedClass1;
}
public class Class2
{
public Wrapper Wrapped;
public Class2(Wrapper wrapper)
{
Wrapped = wrapper;
}
public void ChangeClass1()
{
WrappedClass1.WrappedClass1 = new Class1();
}
}
Class1 class1 = new Class1();
Wrapper wrapper = new Wrapper();
wrapper.WrappedClass1 = class1;
Class2 class2 = new Class2(wrapper);
class2.ChangeClass1();
MessageBox.Show(wrapper.WrappedClass1 == class2.Wrapped.WrappedClass1); // <--- true
Related
Here's what I have:
public partial class MainWindow : Window
{
IMainUIHandler MainUIHandler;
public MainWindow()
{
//InitializeComponent();
IMainUIHandler UIHandlerMain = new MainUIHandler();
UIHandlerMain.PlayerMgtHandler.AddNewPlayer("2020", "_", 1, 3);
... more stuff
}
}
class MainUIHandler : IMainUIHandler
{
public IPlayerMgtUIHandler PlayerMgtHandler { get; }
public MainUIHandler()
{
PlayerMgtHandler = new PlayerMgtUIHandler();
}
}
class PlayerMgtUIHandler : IPlayerMgtUIHandler
{
public List<IPlayer> NewPlayers { get; } //TODO change List to HashSet
public void AddNewPlayer(string idPrefix, string idSeparator, int idSeqNumber,int idNumDigits)
{
IPlayer player=new Player(idPrefix,idSeparator,idSeqNumber,idNumDigits);
NewPlayers.Add(player);
}
public PlayerMgtUIHandler()
{
List<IPlayer> NewPlayers = new List<IPlayer>();
}
}
Stepping through beginning at MainWindow from IMainUIHandler UIHandlerMain = new MainUIHandler();, when I get to:
public PlayerMgtUIHandler()
{
List<IPlayer> NewPlayers = new List<IPlayer>();
}
the List<IPlayer> NewPlayers is not nothing; it has zero elements. When I step out back to the caller PlayerMgtHandler.NewPlayers is null.
What am I doing wrong?
Changed class PlayerMgtUIHandler to:
class PlayerMgtUIHandler : IPlayerMgtUIHandler
{
public List<IPlayer> NewPlayers { get; protected set; } //TODO change List to HashSet
public void AddNewPlayer(string idPrefix, string idSeparator, int idSeqNumber,int idNumDigits)
{
IPlayer player=new Player(idPrefix,idSeparator,idSeqNumber,idNumDigits);
NewPlayers.Add(player);
}
public PlayerMgtUIHandler()
{
NewPlayers = new List<IPlayer>();
}
}
Now it works as I wanted. Thanks for pointing me in the right direction.
I have following code:
public class A
{
public int MyProperty {get; set;}
}
public class B
{
A myInstance = new A();
myInstance.MyProperty = 10;
}
public class C
{
public void InvokeA()
{
//How to access MyPropery here?
BInstance = new B();
Console.WriteLine(B.myInstance.MyProperty.ToString());
}
}
I'm looking for a way to access MyProperty as written above. Inheritance is not an option since my class C is already inherited from some base class. A way without declaring any of the given classes as static would be nice!
Thanks,
Orz
Consider following classes:
public class A
{
public int MyProperty { get; set; }
}
public class B
{
public A GetAInstance()
{
A myInstance = new A();
myInstance.MyProperty = 10;
return myInstance;
}
}
public class C
{
private B BInstance;
public void InvokeA()
{
BInstance = new B();
Console.WriteLine(BInstance.GetAInstance());
}
}
and then you will create your C instance in Main:
static void Main(string[] args)
{
C cInstance = new C();
cInstance.InvokeA();
}
In order to accomplish your goal, you need to expose B.MyInstance as a property of the B class, just like you exposed A.MyProperty as a property of the A class.
Edit: Per the comments of others regarding use of the static keyword, here's what you might want your code to look like:
public class A
{
public int MyProperty { get; set; }
}
public static class B
{
static B()
{
MyInstance = new A();
MyInstance.MyProperty = 10;
}
public static A MyInstance { get; set; }
}
public class C
{
// not sure what your intention is here
public C()
{
System.Console.WriteLine(B.MyInstance.MyProperty.ToString()); // "10\n"
}
}
Yes. You can inherits classes from A to B something like this:
public class A
{
public int MyProperty {get; set;}
}
public class B : A
{
public B()
: A()
{
MyProperty = 1;
}
}
Now you can do:
(new B()).MyProperty
Or use Singleton approach to resolve:
public class B
{
private static _a;
public class A
{
public int MyProperty {get; set;}
}
public static A AA {
if (_a == null) {
_a = new A();
}
return _a;
}
}
This implmentation will return
B.A.MyProperty.ToString();
This question already has answers here:
Virtual member call in a constructor
(18 answers)
Closed 8 years ago.
Is it wrong to initialize a virtual property in the constructor? It just does not feel right because if you override the property in a derived class the property will first be initialized with the value from the base class constructor then it will be assigned again by the derived class constructor. is there an alternative for doing this? I'm talking about something like this
internal class B1
{
public B1()
{
Ti = "Hello";
}
public virtual string Ti { get; set; }
}
internal class B2 : B1
{
public B2()
{
Ti = "HelloKitty";
}
public override string Ti { get; set; } //<--"Hello" will be assigned first then "HelloKitty" will be assigned
}
internal class Program
{
private static void Main(string[] args)
{
var b2 = new B2();
Console.WriteLine(b2.Ti);
Process.GetCurrentProcess().WaitForExit();
}
}
UPDATE 1:
As recommended by #AK_
internal class Bb1
{
private string _ti;
public Bb1()
{
_ti = "Hello";
}
public virtual string Ti
{
get { return _ti; }
set { _ti = value; }
}
}
internal sealed class Bb2 : Bb1
{
public Bb2()
{
Ti = "HelloKitty";
}
public override string Ti { get; set; }
}
the variable _ti in the base class is initialized by "Hello".
what if instead of string type I'm using type which explicitly needs to be exposed?
On the other hand this is reasonable (notice that B2 is sealed )
internal class B1
{
private string m_ti;
public virtual string Ti { get{return m_ti;} set{m_ti = value;} }
public B1()
{
m_ti = "Hello";
}
}
internal sealed class B2 : B1
{
public B2()
{
Ti = "HelloKitty";
}
public override string Ti { get; set; } //<--"Hello" will be assigned first then "HelloKitty" will be assigned
}
another option a protected constructor:
internal class B1
{
private string m_ti;
public virtual string Ti { get { return m_ti; } set { m_ti = value; } }
public B1()
{
m_ti = "Hello";
}
protected B1(String word)
{
m_ti = word;
}
}
internal sealed class B2 : B1
{
public B2():base("kitty")
{
}
}
Please first take a look at this simple code;
This is my base class:
public class BaseClass
{
public BaseClass()
{
}
public BaseClass(BaseClass b)
{
}
public virtual string GetMSG()
{
return "Base";
}
}
and this is the derived one:
public class DrivenClass : BaseClass
{
public string MSG { get; set; }
public DrivenClass(string msg)
{
MSG = msg;
}
public DrivenClass(DrivenClass d)
{
MSG = d.MSG;
}
public override string GetMSG()
{
return MSG;
}
}
and this is the test:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public BaseClass B { get; set; }
public DrivenClass D { get; set; }
private void button1_Click(object sender, EventArgs e)
{
D = new DrivenClass("Driven");
B = new BaseClass(D);
MessageBox.Show("B:" + B.GetMSG() + "\nD:" + D.GetMSG());
}
}
Now my question is what should I do that B = new BaseClass(D); works like B = new DrivenClass(D); ?
I'm using this in polymorphism and I like to use one copy-constructor instead of different driven ones.
I want the output like this :
Driven
Driven
but now it's like this :
Base
Driven
You can use an overridden virtual Copy method instead of a copy constructor.
public class BaseClass
{
public BaseClass()
{
}
public virtual BaseClass ShallowCopy()
{
return new BaseClass();
}
public virtual string GetMSG()
{
return "Base";
}
}
public class DrivenClass : BaseClass
{
public string MSG { get; set; }
public DrivenClass(string msg)
{
MSG = msg;
}
public override BaseClass ShallowCopy() {
return new DrivenClass(this.MSG);
}
public override string GetMSG()
{
return MSG;
}
}
Then call it like this:
D = new DrivenClass("Driven");
B = D.ShallowCopy();
This will work because calling a virtual method always calls the actual overriden implementation in the subclass, even when called from the baseclass interface.
What happens is normal because you create new instance of base class here. Therefore you never override the GetMSG method:
B = new BaseClass(D);
What you wanted to do is to have the same public class:
public BaseClass B { get; set; }
and to give it the value of new DrivenClass(D)
B = new DrivenClass(D);
Imagine a class as follows.. It's a class provided to me to work with.. I cannot change its source..
public class MyClass
{
object _Object { get; set; }
public void FuncA1() { _Object = new object(); }
public void FuncA2() { _Object = new List<object>(); }
public int FuncB1() { _Object = 0; return 0; }
public int FuncB2() { _Object = 123; return 123; }
public string FuncC1() { _Object = null; return null; }
public string FuncC2() { _Object = "Hello"; return "Hello"; }
}
Im trying to create a wrapper for this class, such that I can group its many functions into categories..
MyWrapper.Voids.FuncA1();
MyWrapper.Voids.FuncA2();
MyWrapper.Integers.FuncB1();
MyWrapper.Integers.FuncB2();
MyWrapper.Strings.FuncC1();
MyWrapper.Strings.FuncC2();
The only solution I can think of for this scenario is to design the wrapper like this:
public class MyWrapper
{
MyClass _Instance { get; set; }
public _Void Voids { get; private set; }
public _Integer Integers { get; private set; }
public _String Strings { get; private set; }
public class _Void
{
MyWrapper _Parent { get; set; }
public void FuncA1() { _Parent._Instance.FuncA1(); }
public int FuncA2() { return _Parent._Instance.FuncA2(); }
}
public class _Integer
{
...
}
public class _String
{
...
}
public MyWrapper()
{
_Instance = new MyClass();
Voids = new _Voids(this);
Integers = new _Integer(this);
Strings = new _String(this);
}
}
This solution works, but has a number of problems:
- The inner classes are forced to be public, which allows them to be instantiated by the user..
- I am forced to maintain a reference of the parent object in the child classes..
Is there a better way of doing this?
EDIT: The code posted initially was a bit confusing, in the sense that it was diverting attention away from the core issue and more into the issues of whether a function would cause exceptions or not if they all work on the same object..
NOTE: This is not actual code.. I hacked together this example to show what I'm trying to do.. CREATE A WRAPPER AROUND AN OBJECT (I cannot change the original object's code) AND GROUP FUNCTIONS INTO CATEGORIES..
FINAL EDIT: following suggestion by Juharr.. here's what ive done to accomplish what i wanted.. for the betterment of others..
public interface IVoid
{
void FuncA1();
void FuncA2();
}
public interface IInteger
{
int FuncB1();
int FuncB2();
}
public class MyWrapper
{
public MyClass Instance { get; private set; }
public IVoid Voids { get; private set; }
public IInteger Integers { get; private set; }
private abstract class MyBase
{
protected MyWrapper Parent { get; set; }
protected MyClass Instance { get { return Parent.Instance; } }
public MyBase(MyWrapper oParent) { Parent = oParent; }
}
private class MyVoid : MyBase, IVoid
{
public MyVoids (MyWrapper oParent) : base(oParent) { }
public void FuncA1() { Instance.FuncA1(); }
public void FuncA2() { Instance.FuncA2(); }
}
private class MyInteger : MyBase, IInteger
{
public MyInteger (MyWrapper oParent) : base(oParent) { }
public int FuncB1() { return Instance.FuncB1(); }
public int FuncB2() { return Instance.FuncB2(); }
}
public MyWrapper()
{
Instance = new MyClass();
Voids = new MyVoid(this);
Integers = new MyInteger(this);
}
}
You could write public interfaces instead. Then your inner classes don't have to be public. So something like this.
public interface IIntger
{
void Set(int iValue);
int Get();
}
public class MyWrapper
{
MyClass _Instance { get; set; }
public IInteger Integer { get; private set; }
private class _Integer : IInteger
{
MyWrapper _Parent { get; set; }
public void Set(int iValue) { _Parent._Instance.IntegerSet(iValue); }
public int Get() { return _Parent._Instance.IntegerGet(); }
}
public MyWrapper()
{
_Instance = new MyClass();
Integer = new _Integer(this);
}
}
EDIT:
To answer the second part of your question you will either need the reference to the parent class or a reference to the class you are wrapping. So you could have this instead.
public class MyWrapper
{
public IInteger Integer { get; private set; }
private class _Integer : IInteger
{
MyClass _Instance { get; set; }
public _Integer(MyClass myClass) { _Instance = myClass; }
public void Set(int iValue) { _Instance.IntegerSet(iValue); }
public int Get() { return _Instance.IntegerGet(); }
}
public MyWrapper(MyClass instance)
{
Integer = new _Integer(instance);
}
}