Two Interacting C# Classes - c#

This is a pretty beginner question but I'm stumped and I can't figure out how to get what I want from this. I have my first class that obtains information (database/textfile/whatever) but I want it to relay that information into Class2.
For instance, the first:
public class Class1
{
private int first;
private string firstString;
private bool isTrue;
public void SomeMethod()
{
first = 1;
firstString = "FirstString";
isTrue = true;
}
}
Here SomeMethod sets all the attributes that I need to pass into Class2.
ClassTwo looks like
public class Class2
{
private int first;
private string FirstString;
private bool isTrue;
private int second;
private string SecondString;
private bool isFalse;
public void SomeOtherMethod()
{
}
}
Here what I want is for SomeOtherMethod() to set the first set of attributes with the values that were set in Class1's SomeMethod(). So that I can create an object of type Class2 and add what I want to it.

As some other commentators stated, you really should reuse your data definitions. Something like this can get you started:
public class Class1
{
private int _myInt;
private string _myString;
private bool _myBool;
public void SomeMethod()
{
_myInt = 1;
_myString = "FirstString";
_myBool = true;
}
}
public Class2
{
private Class1 _first = new Class1();
private Class1 _second = new Class1();
public void SetFirst(Class1 obj)
{
_first = obj;
}
}
and then use the classes like this:
Class1 c1 = new Class1();
Class2 c2 = new Class2();
c1.SomeMethod();
c2.SetFirst(c1);

You have to define get accessors for the properties of Class1 because they are all unreachable from outside the class and Class2 needs to use their values. Defining public properties with get accessors can be useful:
private int first;
public int First
{
get
{
return first;
}
}
Having every property in Class1 defined like this, you can access the values. After calling SomeMethod, two objects' properties can be equalized in two simple ways (See also: Signatures and overloading):
public void SomeOtherMethod()
{
Class1 tempClass = new Class1();
tempClass.SomeMethod();
this.first = tempClass.first;
this.FirstString = tempClass.firstString;
this.isTrue = tempClass.isTrue;
}
public void SomeOtherMethod(Class1 myClass) // Overloaded method
{
this.first = myClass.first;
this.FirstString = myClass.firstString;
this.isTrue = myClass.isTrue;
}
Even though the techniques above seem like to be what you asked for, the best is to initialize a class's properties using constructors. This way, you don't have to call SomeMethod each time you create a Class1 object, and you can also set its default values whenever a new one is created. Also, giving more general names to the properties will save you from duplicates. I write some code to provide you an understandable syntax that will prevent future problems of non-accessibility and repetition.
public class Class1
{
private int number;
public int Number
{
get { return number; }
}
private string name;
public string Name
{
get { return name; }
}
private bool isTrue;
public bool IsTrue
{
get { return isTrue; }
}
public Class1()
{
number = 1;
name = "FirstString";
isTrue = true;
}
public Class1(int value1, string value2, bool value3)
{
number = value1;
name = value2;
isTrue = value3;
}
}
public class Class2
{
private Class1 firstClass;
private Class1 secondClass;
public Class2()
{
firstClass = new Class1();
secondClass = new Class1(2, "SecondString", false);
}
}
If you're going to define many Class1 objects in Class2, then a solution such as an array or a list becomes must. I'll give a short example, see MSDN List page.
private List<Class1> class1List = new List<Class1>();
class1List.Add(new Class1());
class1List.Add(new Class1(2, "SecondString", false));

Related

string created from variable in c#

Is it possible to to define a string from a variable where the string does NOT have quotations. Example:
public class aclass
{
public string athing;
}
public void example(string thing)
{
aclass thing = new aclass();
}
The string thing can't be put into aclass thing = new aclass(); normaly.
Is there anyway to do it?
You need a constructor
void Main()
{
CreateExampleObject("testing");
}
public class Example
{
// This is a constructor that requires a string as an argument
public Example(string text)
{
this.Text = text;
}
public string Text { get; set; }
}
public void CreateExampleObject(string text)
{
Example example = new Example(text);
Console.WriteLine(example.Text);
}
You can do it this using many way but generally standard way is using constructor
please refer this link for better understanding.
C# : assign data to properties via constructor vs. instantiating
You have to ways of setting fields/property value of an object.
First is to do it through the constructor, as mentioned in other answer.
Second can be implmeneted in various ways:
Expose public property making field privte:
public class aclass
{
private string _athing;
public string Athing
{
get { return _athing; }
set { _athing = value; }
}
}
public void example(string thing)
{
aclass aclass = new aclass();
aclass.Athing = thing;
}
Or even shorter, you could use property:
public class aclass
{
public string Athing {get; set; }
}
Using your implementation, you make your field public, so you can set it easily:
public void example(string thing)
{
aclass aclass = new aclass();
aclass.athing = thing;
}
But it doesn't comply with OOP encapsulation principle.

C# uncommon access to object's properties

I have several master objects. Each ot them has list of slave objects. Each of the slave objects has two fields: field1 and field2. I need to have access to the fields from the main objects ONLY if the main object, who asked for the field, is not an owner of the slave object.
class SlaveObj()
{
...
private readonly int field1;
private readonly string field2;
...
public int GetField1()
{
// if asker object is not my owner
// return field1
}
}
class MainObj()
{
...
List<SlaveObj> slaves = new List<SlaveObj>();
...
public int GetField1(MainObj other)
{
return other.slaves[0].GetField1();
}
}
First, what I tried, was this. I just tried to check, like in the first answer, what object is the asker. But I have something like Project1.MainObj for any instance of MainObj. So, I can't recognize whether the asker is the owner or not.
Code after changes (not works as i want)
class SlaveObj()
{
...
private MainObj owner;
private readonly int field1;
private readonly string field2;
...
public int GetField1(MainObj asker)
{
if(asker != owner) return field1;
}
}
class MainObj()
{
...
List<SlaveObj> slaves = new List<SlaveObj>();
...
public int GetField1(MainObj other)
{
return other.slaves[0].GetField1(this);
}
}
My friend, this should work out the way you need. But you gotta add IDs to parent objects.
internal class SlaveObj
{
private MainObj owner;
private readonly int field1;
private readonly string field2;
public SlaveObj(MainObj parent)
{
this.owner = parent;
}
public int GetFieldID(int askerID)
{
if (askerID != owner.ID) return field1;
return 0;
}
}
class MainObj
{
public int ID;
List<SlaveObj> slaves = new List<SlaveObj>();
public int GetFieldID(MainObj other)
{
return other.slaves[0].GetFieldID(this.ID);
}
public MainObj(int id)
{
this.ID = id;
}
}
And your previous version did not work out because your main objects are of reference type thich are compared by reference by default. So better use object IDs implement IEqualtyComparer in MainObj:
class MainObj : IEqualityComparer
It's easy to fix
class SlaveObj()
{
MainObj _owner;
readonly int _field1 = ...;
readonly string _field2 = ...;
// you need a way to set owner, e.g. constructor parameter
public SlaveObj(MainObj owner)
{
_owner = owner; // good example why underscore in field name is good
}
// return type: object
// renamed
// using C# 6.0 features to confuse people
public object GetFieldX(MainObj asker) => asker != _owner ? _field1 : _field2;
}
class MainObj()
{
List<SlaveObj> _slaves = new List<SlaveObj>();
// return first slave field value
// has nothing to do with instance, therefore static
// will return null if no slave
public static object GetFieldX(MainObj owner) => owner?.FirstOrDefault()?.GetFieldX(this);
}
but it's not pretty.

C# Calling variables from other classes

this is probably very simple, but I have always just made one big class and never tried make clean code. Now I am trying and experiencing errors..
So, this is the idea:
class1
{
method1 { value 1; value 2 }
method2 { value 3; value 4 }
method3 { uses method4 from class2 }
}
class2
{
method4 { uses values 1-4 from class1 }
}
I am doing it by calling: class1 c1 = new class1() in method4 and class2 c2 = new class2 in method3.
So this is what happens:
method1, method2 produce values 1-4
method3 calls class2 c2 = new class2
I get into class2, then into method4 and get null/0 values instead of what I made in first step.
Instead of creating a new instance of class1 in method4 you should pass the current class1 instance (accessible through this inside method3) as a parameter to this method to get the same result.
You need to be more specific...
class Class1
{
Class2 _class2;
public Class1(Class2 class2)
{
_class2 = class2;
}
public void method3()
{
//call _class2.method4()
}
}
class Class2
{
Class1 _class1;
public Class2(Class1 class1)
{
_class1 = class1;
}
public void Method4()
{
//call _class1.MethodWhatever()
}
}
So when you need to access variables within a class you can obviously do this simply via the 'public' modifier, however the below example is not best practice but we will get onto that shortly...
public class MyTestClass
{
public int MyAge;
}
This is a field - fields should really be private, and we should use a property to expose the field. However if you did do this, then you can access that like so:
var foo = new MyTestClass();
var hisAge = foo.MyAge;
Of course based on your requirements maybe you don't want the user to access the variable directly, but rather get a value after some computation has been done on other variables.
You can do this like so:
public class MyTestClass
{
private int _gamesPlayed;
private int _gamesLost;
public int NumberOfWins { get { return _gamesPlayed - _gamesLost; } }
}
NumberOfWins is a Property. It computes the values of two of our fields and reutrns it. See how we have the private modifier, these can't been seen outside of the scope of that class. NumberOfWins can be accessed the same way as MyAge in the previous example.
To be honest, it sounds like you are rather using pseudo-code or are a beginner.
I recommend checking out the following articles for a bit more information on what I have stated.
Modifiers - C# Reference
Properties C# Programming Guide
Difference between a Field and a Property in C#
it is really unclear what you want to achieve and how class1 is linked to class2. If your class2 is ONLY useful for the first class then (and only then) you could use nested classes...
class OuterClass {
string value1;
string value2;
string value3;
// ...
class InnerClass
{
OuterClass o_;
public InnerClass(OuterClass o)
{
o_ = o;
}
public string GetOuterString()
{
return o_.value1 + o.value2 + o.value3; //...
}
}
void SomeFunction()
{
InnerClass i = new InnerClass(this);
i.GetOuterString();
}
}
This would create a clear binding from the inner class (class 2) to the outer one. It is not easier though.
Edit: OK, after your edit I see a whole different story..
Well, here is some code for you. I'm not sure it it's what you require. It might help you get started, though. You can try running it here: https://dotnetfiddle.net/#
This is Class1. It exposes some of its data via properties.
public class Class1
{
// these are properties
public int Value1 { get; set; }
public int Value2 { get; set; }
public int Value3 { get; set; }
public int Value4 { get; set; }
public void Method1()
{
Value1 = 1;
Value2 = 2;
}
public void Method2()
{
Value3 = 3;
Value4 = 4;
}
public void Method3()
{
// uses method4 from class2
var c = new Class2();
c.Method4();
}
}
This is Class2. It calls methods from Class1 and accesses its properties.
public class Class2
{
public void Method4()
{
//uses values 1-4 from class1
var c = new Class1();
c.Method1();
c.Method2();
Console.WriteLine(c.Value1);
Console.WriteLine(c.Value2);
Console.WriteLine(c.Value3);
Console.WriteLine(c.Value4);
}
}
This uses both closes and shows the result:
using System;
public class Program
{
public static void Main()
{
var c1 = new Class1();
c1.Method3();
}
}

Reaching public property of parent class

a simple question :
public class class1
{
public string string1;
public class class2
{
public string string2
{
get{ string tmp = class1.string1; }
}
}
}
I want to be able to reach class1.string1 from class2.string2.get, but I cant. What would you recommend me to change, so that I can do that?
Thanx
Passing class1 reference to class2 in constructor:
public class class1 {
public string string1;
public class class2 {
private class1 _Reference;
public class2(class1 reference) {
if (reference == null) {
throw new ArgumentNullException("reference");
}
_Reference = reference;
}
public string string2 {
get { return _Reference.string1; }
}
}
}
Passing class1 reference to class2 after both classes have been created:
public class class1 {
public string string1;
public class class2 {
private class1 _Reference;
public class1 Reference {
set { _Reference = value; }
}
public string string2 {
get { return _Reference.string1; }
}
}
}
static void usage() {
var foo = new class1();
var bar = new class1.class2();
bar.Reference = foo;
string value = bar.string2;
}
There is no means of accessing a class from within a nested class that I know of. Class nesting doesn't lead to automatic instantiation of the surrounding class, it's just a (usually rather smelly) means of structuring your code.
You would either need a reference to an actual instance of Class1 inside Class2 or you'd need a static method on Class1.
Another way to accomplish this would be to use inheritance, but that's a whole different beast to tame:
public class Class1 {
protected String String1 { get; set; }
}
public class Class2 : Class1 {
public String String2 {
get {
String PropertyFromClass1 = base.String1;
// ...
}
}
}
That said: Your code wouldn't compile, string2's getter doesn't return anything. And please make yourself familiar with C#'s naming conventions.
Thanx for the suggestions. Due to the specific nature of the code, I had to solve this situation with a global public static class in another namespace.
Coming from Java I faced this "problem" when I started developing in C#.
As clearly explained by Dennis Traub and in this article in C# you can't access outer class members or methods. So you have to implement what in Java happens automatically:
class OuterClass {
string s;
// ...
class InnerClass {
OuterClass o_;
public InnerClass(OuterClass o) { o_ = o; }
public string GetOuterString() { return o_.s; }
}
void SomeFunction() {
InnerClass i = new InnerClass(this);
i.GetOuterString();
}
}

Strange behaviour with static fields

I am trying to get a custom enum class working which should enable me to create enums with user friendly identifiers and an arbitrary associated value. so far so good:
public class EnumBase<T, E>
where E : class
{
private static readonly List<E> list = new List<E>();
private string text;
private T value;
public string Text { get { return text; } }
public T Value { get { return value; } }
public EnumBase(string text, T value)
{
this.text = text;
this.value = value;
list.Add(this as E);
}
protected static IEnumerable<E> ItemList
{
get { return list; }
}
}
public class Zahlungsart : EnumBase<int, Zahlungsart>
{
public static readonly Zahlungsart Erlagsschein = new Zahlungsart("Erlagsschein", 0);
public static readonly Zahlungsart Lastschrift = new Zahlungsart("Lastschrift", 1);
private Zahlungsart(string text, int value) : base(text, value) { }
public static new IEnumerable<Zahlungsart> ItemList { get { return EnumBase<int, Zahlungsart>.ItemList; } }
}
And now my problem:
Console.WriteLine(Zahlungsart.ItemList.Count());
The following statement gives me 0, instead of 2. The problem is due to beforefieldinit, I think. I could work around this by calling some method of the specific enum directly which would force the static fields to load, but this is not the best solution, I think.
Hint: please do not propose some kind of [UserfriendlyName()]-attribute for enum here, I already know them.
EDIT
Thanks, hans. I had indeed a typo in my own code, calling the wrong generic specialisation.
Now my question is, can I get rid of the redefinition of ItemList in each subclass, but it seems this is necessary to to get the static fields initialized.
How about using "static constructor" ??
public class Zahlungsart : EnumBase<int, Zahlungsart>
{
public static readonly Zahlungsart Erlagsschein;
public static readonly Zahlungsart Lastschrift;
static Zahlungsart()
{
Erlagsschein = new Zahlungsart("Erlagsschein", 0);
Lastschrift = new Zahlungsart("Lastschrift", 1);
}
private Zahlungsart(string text, int value) : base(text, value) { }
public static new IEnumerable<Zahlungsart> ItemList { get { return EnumBase<int, Zahlungsart>.ItemList; } }
}
Your code doesn't repro the problem. But you will get a repro if you change the property like this:
public new static IEnumerable<Zahlungsart> ItemList {
get { return EnumBase<uint, Zahlungsart>.ItemList; } // Note: uint instead of int
}
Beware that every concrete class generated from a generic type will have its own static fields, they are not shared.

Categories

Resources