I have code like this:
class First
{
public int a { get; set; }
public int b { get; set; }
public int c = 2;
public _second;
public First()
{
_second = new Second(c);
this.a = _second.a;
this.b = _second.b;
}
}
class Second
{
public int a;
public int b;
public Second(int c)
{
if(c == 0)
{
a = 1;
b = 2;
}
else
{
a = -1;
b = -2;
}
}
}
How can I pass a and b from First class into second class and then directly from second class set their values withohut using static as declaration in First class.
I have tried this:
class First
{
public int a;
public int b;
public int c = 2;
public _second;
public First()
{
_second = new Second(a, b, c);
}
}
class Second
{
public Second(int a, int b, int c)
{
if(c == 0)
{
a = 1;
b = 2;
}
else
{
a = -1;
b = -2;
}
}
}
but it is not doing the job.
You can simply add a constructor in the Second class that receives the instance of First and updates the public variables of the instance passed
public class Second
{
public Second(int a, int b, int c)
{
// old constructor if still needed
...
}
public Second(First f)
{
int sign = f.c == 0 ? 1 : -1;
f.a = 1 * sign;
f.b = 2 * sign;
}
}
By the way, I suggest to use properties instead of public fieds.
public class First
{
public int a {get;set;}
public int b {get;set;}
public int c {get;set;} = 2;
public Second _second {get;set;}
public First()
{
_second = new Second(this);
}
}
UPDATE
Looking at your image it is clear what is the source of your problem. You are receiving a Form class instance in your Forma constructor. You need to receive a Main instance like
public Forma(Main form, int modulID)
{
.....
}
The base class Form has no knowledge of methods defined in custom form classes. In alternative you can still receive a Form instance but you need to add something like this
public Forma(Form form, int modulID)
{
Main m = form as Main;
if(m != null)
m.helpWindow = new Help(modulID);
}
.....
}
You can pass the fields as ref meaning that you pass a reference to the field passed as parameter not the value. This means changes to the fields inside the Second constructor will be reflected in the First class
class First
{
public int a;
public int b;
public int c = 2;
public Second _second;
public First()
{
_second = new Second(ref a, ref b, c);
}
}
class Second
{
public Second(ref int a, ref int b, int c)
{
if (c == 0)
{
a = 1;
b = 2;
}
else
{
a = -1;
b = -2;
}
}
}
You can pass by ref to any method not just a constructor. You should read more about this topic, here for example
I accomplished it with Interface.
public interface IClass
{
int a { get; set; }
int b { get; set; }
}
class First : IClass
{
public int a { get; set; }
public int b { get; set; }
public int c = 2;
public _second;
public First()
{
_second = new Second(this, c);
}
}
class Second
{
public Second(IClass ic, int c)
{
if(c == 0)
{
ic.a = 1;
ic.b = 2;
}
else
{
ic.a = -1;
ic.b = -2;
}
}
}
Related
how do I set id in Sprite from the template templa
public class templa<T> where T : class , new(){
public T CreateMe(){
T temp = new T();
shortInt si
si.Set(2, 2);
//T needs to have id as shortInt else it won't work
temp.id = si; // temp = si// doesn't work either
return temp;
}
}
public struct shortInt{
public short s;
public int i;
public void Set(short s, int i){
this.s = s;
this.i = i;
}
}
Sprite here has id this is what I'm trying to achieve to change id with template
public class Sprite{
public Sprite(){}
public shortInt id;
set{
id = value;
}
}
I was searching the web and found only do it with { get; set; } I'm clueless here
using where(generic type constraint)
code like this
public class Templat<T> where T :
Sprite, new() //constraint in here
{
public T CreateMe()
{
T temp = new T();
shortInt si = new shortInt();
si.Set(2, 2);
temp.id = si;
return temp;
}
}
public struct shortInt
{
public short s;
public int i;
public void Set(short s, int i)
{
this.s = s;
this.i = i;
}
}
public class Sprite
{
public Sprite() { }
public shortInt id { get; set; }
}
My class looks like this:
public class MyClass
{
private void MyClass() { } //just to satisfy the XML serializer
public void MyClass(int a, int b)
{
A = a;
B = b;
C = a + b;
}
public int A { get; set; }
public int B { get; set; }
public int C { get; private set; } //private set is only to
//satisfy the XML Serializer
public void DoSomeMath()
{
Console.WriteLine("{0} + {1} = {2}\n", A, B, C)
}
}
This works fine when I instantiate my own myClass object with a & b parameters, but the deserializer will only call the paramaterless constructor. How do I initialize C without creating another method and calling that after I deserialize?
Deserializing will just populate the variables - any other logic required to instantiate the object needs to be run by the program, not the deserializer. Try something like this:
public class MyClass
{
private void MyClass() // NOT just to satisfy the XML serializer
{
GetStuffReady();
}
public void MyClass(int a, int b)
{
A = a;
B = b;
GetStuffReady();
}
public int A { get; set; }
public int B { get; set; }
public int C { get; private set; }
public void GetStuffReady()
{
C = A + B;
}
public void DoSomeMath()
{
Console.WriteLine("{0} + {1} = {2}\n", A, B, C)
}
}
Or better yet:
public class MyClass
{
private void MyClass() { } //just to satisfy the XML serializer
public void MyClass(int a, int b)
{
A = a;
B = b;
}
public int A { get; set; }
public int B { get; set; }
public int C
{
get
{
return A + B;
}
set { }
}
public void DoSomeMath()
{
Console.WriteLine("{0} + {1} = {2}\n", A, B, C)
}
}
EDIT: If the variables need to be set before the logic is executed, you can create a blank instance of the class and then set the variables using a helper method that takes XML as an input. See the following answer for an example: When is the class constructor called while deserialising using XmlSerializer.Deserialize?
You can simply modify the getter for C like:
public int C { get { return this.A + this.B; }}
If you are using the regular binary formatter, then:
[OnDeserialized]
public void DoSomeMath()
{
Console.WriteLine("{0} + {1} = {2}\n", A, B, C)
}
For the XmlSerializer, events are not supported.
You could implement IXmlSerializable, but it's non trivial.
For DataContractSerializer (which serializes to xml) you could try:
[OnDeserializing]
public void OnDeserializing(StreamingContext context)
{
... // logic here.
}
There is an answer here to XmlSerializer but it requires inheriting the default one.
How do you find out when you've been loaded via XML Serialization?
I have a big class with a lot of properties (BigClass). I need to make a new class (SmallClass) with only some of those properties. This SmallClass must use all the overlapping properties from BigClass. What is the easiest way to do this without having to manually assign all the properties in the constructor of SmallClass like I do below:
class BigClass
{
public int A { get; }
public int B { get; }
public int C { get; }
public int D { get; }
public int E { get; }
public BigClass(int a, int b, int c, int d, int e)
{
A = a;
B = b;
C = c;
D = d;
E = e;
}
}
class SmallClass
{
public int A { get; }
public int B { get; }
public int C { get; }
public SmallClass(BigClass bigClass)
{
// I don't want to do all this manually:
A = bigClass.A;
B = bigClass.B;
C = bigClass.C;
}
}
Create a helper class:
public class Helper
{
public static void CopyItem<T>(BigClass source, T target)
{
// Need a way to rename the backing-field name to the property Name ("<A>k__BackingField" => "A")
Func<string, string> renameBackingField = key => new string(key.Skip(1).Take(key.IndexOf('>') - 1).ToArray());
// Get public source properties (change BindingFlags if you need to copy private memebers as well)
var sourceProperties = source.GetType().GetProperties().ToDictionary(item => item.Name);
// Get "missing" property setter's backing field
var targetFields = typeof(T).GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField).ToDictionary(item => renameBackingField(item.Name));
// Copy properties where target name matches the source property name
foreach(var sourceProperty in sourceProperties)
{
if (targetFields.ContainsKey(sourceProperty.Key) == false)
continue; // No match. skip
var sourceValue = sourceProperty.Value.GetValue(source);
targetFields[sourceProperty.Key].SetValue(target, sourceValue);
}
}
}
Then in your SmallClass constructor:
public SmallClass(BigClass bigClass)
{
Helper.CopyItem(bigClass, this);
}
This should work even if you only have property getters.
You can make CopyItem to work with all types by changing its declaration;
public static void CopyItem<U, T>(U source, T target)
I have these classes in my project:
public class A
{
public A(B b, C c)
{
this.b = b;
this.c = c;
}
B b;
C c;
}
public class B
{
public B(DataRow row)
{
if (row.Table.Columns.Contains("Property3 "))
this.Property3 = row["Property3 "].ToString();
if (row.Table.Columns.Contains("Property4"))
this.Property4= row["Property4"].ToString();
}
public string Property3 { get; set; }
public string Property4{ get; set; }
public object MyToObject()
{
}
}
public class C
{
public C(DataRow row)
{
if (row.Table.Columns.Contains("Property1 "))
this.Property1 = row["Property1 "].ToString();
if (row.Table.Columns.Contains("Property2 "))
this.Property2 = row["Property2 "].ToString();
}
public string Property1 { get; set; }
public string Property2 { get; set; }
}
I want to take an object as output from MyToObject function that is declared in class A; that output object contains all of the properties of b and c, like this:
output object = {b.Property3 , b.Property4 , c.Property1 , c.Property2 }
Unless I'm missing something, you've just about got it:
public dynamic MyToObject(B b, C c)
{
return new
{
BUserName = b.UserName,
BPassword = b.PassWord,
CUserName = c.UserName,
CPassword = c.PassWord
}
}
Now that you've created a dynamic object you can use it like this:
var o = a.MyToObject(b, c);
Console.WriteLine(o.BUserName);
Try this:
public class D
{
public string UserNameB { get; set; }
public string PasswordB { get; set; }
public string UserNameC { get; set; }
public string PassWordC { get; set; }
public D(B b, C c)
{
UserNameB = b.UserName;
PasswordB = b.PassWord;
UserNameC = c.UserName;
PassWordC = c.PassWord;
}
}
and then your ToMyObject method can just be this:
public static D ToMyObject(B b, C c)
{
return new D(b, c);
}
Or you could also use a Tuple<B, C>:
public static Tuple<B, C> ToMyObject(B b, C c)
{
return Tuple.Create(b, c);
}
You could also be a bit cheeky and use anonymous objects, but that's very dangerous:
public dynamic MyToObject(B b, C c)
{
return new { UserNameB = b.UserName, PassWordB = b.PassWord,
UserNameC = c.UserName, PassWordC = c.PassWord }
}
I have a class
class TestFixture
{
public string a { get; set; }
public int b { get; set; }
public int c { get; set; }
public string d { get; set; }
public string e { get ; set ; }
public int f { get; set; }
public int g { get; set; }
public bool h { get; set; }
public string i { get; set; }
public bool j { get; set; }
public bool k { get; set; }
public TestFixture()
{
e= dosomething(a, b);
f= false;
g = DateTime.Now.ToString("yyMMddhhmmss");
h= TestName.Equals("1") && b.Equals("2") ? 1000 : 1;
i= 10000000;
j= a.Equals("FOT");
k = false;
}
}
I want to define new TestFixture as SO
new TestFixture { a = "", b = 1, c=2, d="" };
while the rest of properties should be auto defined as it written in constructor.
Is it possible ?
Yes, this is possible. Using an object initializer does not skip calling the constructor.
TestFixture fixture = new TestFixture() // or just new TestFixture { ... }
{
a = "",
b = 1,
c = 2,
d = ""
};
This will call the constructor you've defined and then set a, b, c, and d in your object initializer.
Pop a breakpoint in your constructor and run your debugger. This is should show you how and when things in your code are called.
Debugging in Visual Studio
Refactored:
public class TestFixture
{
public string a { get; set; }
public int b { get; set; }
public int c { get; set; }
public string d { get; set; }
// dosomething should check for null strings
public string e { get { return dosomething(a, b); } }
public int f { get; set; }
public int g { get; set; }
public bool h
{
get { return TestName.Equals("1") && b.Equals("2") ? 1000 : 1; }
}
public string i { get; set; }
public bool j { get { return a != null && a.Equals("FOT"); } }
public bool k { get; set; }
public TestFixture(string a, int b, int c, string d)
: this()
{
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
public TestFixture()
{
f = false;
g = DateTime.Now.ToString("yyMMddhhmmss");
i = 10000000;
k = false;
}
}
#hunter's answer is correct, you can use object initializer syntax, and those properties will be set after your constructor runs. However, I'd like to point out some flaws you may have with your code
public TestFixture()
{
e= dosomething(a, b);
f= false;
g = DateTime.Now.ToString("yyMMddhhmmss");
h= TestName.Equals("1") && b.Equals("2") ? 1000 : 1;
i= 10000000;
j= a.Equals("FOT");
k = false;
}
This code does not set a or b, but you have things that depend on their values (e, g, j). Object initializer syntax is not going to be useful here, you have to have proper defaults for these values if other values in the constructor will depend upon them.
As an example, when you write var obj = new Bar() { A = "foo" };, that will expand to
var obj = new Bar(); // constructor runs
obj.A = "Foo"; // a is set
Clearly, the code in the constructor that looks at A will not see the value "Foo". If you need it to see this value, object initialization strategy is not going to help. You need a constructor overload that takes the value to be stored in A.
var obj = new Bar("Foo");
If I understand you right, you would like to the a, b, c and d properties to be initialized with the given values before the constructor runs. Unfortunately, that is not possible this way, because the default constructor always runs before the object intializers.
I advise you to do something like this instead:
class TestFixture
{
//... properties
public TestFixture()
{
this.init();
}
public TestFixture(string a, int b, int c, string d)
{
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.init();
}
private void init()
{
e= dosomething(a, b);
f= false;
g = DateTime.Now.ToString("yyMMddhhmmss");
h= TestName.Equals("1") && b.Equals("2") ? 1000 : 1;
i= 10000000;
j= a.Equals("FOT");
k = false;
}
}
This way you can init the a, b, c and d properties before the other initializer code runs.