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.
Related
I'm trying to modify a bunch of static value variables as fields in a static class. They need to be initialized in some sort of structure with a string attached to them, but the outside world should be able to just get the variable directly.
Here's a basic code dump of what I'm trying to do (disregard the specifics inside of DoStuff(); just an example of the kind of operations I'm trying to do):
public unsafe static class StaticVariables
{
public static int foo;
public static int bar;
...
public static int bazinga;
static IEnumerable<StaticInteger> intList = new List<StaticInteger>
{
new StaticInteger(&foo,"foo"),
new StaticInteger(&bar,"bar"),
...
new StaticInteger(&bazinga,"bazinga")
};
public static void DoStuff()
{
foreach(StaticInteger integer in intList)
{
if(integer.identifier=="foo") *integer.pValue = 30;
if (integer.identifier == "bar") *integer.pValue = 23;
}
Console.WriteLine("{0} {1}", foo, bar);
}
}
public unsafe class StaticInteger
{
public int* pValue;
public string identifier;
public StaticInteger(int* pValue, string identifier)
{
this.pValue = pValue;
this.identifier = identifier;
}
}
I'm not able to grab the address of foo/bar where I want to. They're static/globals, so they shouldn't going anywhere. I can cheat and use fixed inside of DoStuff to initialize the list, but I want to be able to reference my list multiple times after initialization, and I'm not sure that's safe because we'd no longer be in the fixed block. Is there a way to tell the GC "Don't touch where you put this static variable please"?
I'd be super happy if the answer was "don't use pointers, do XYZ instead."
Using a properties with only a getter rather than fields you can limit users to only reading values & the values can be stored in a Dictionary rather than a list.
public static class StaticVariables
{
public static int foo { get {return values["foo"];}}
public static int bar { get {return values["bar"];}}
public static int bazinga { get {return values["bazinga"];}}
private static Dictionary<String,int> values = new Dictionary<String,int>();
static StaticVariables()
{
values.Add("foo",0);
values.Add("bar",0);
values.Add("bazinga",0);
}
public static void DoStuff()
{
values["foo"] =30;
values["bar"] =23;
}
}
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.
I cant access static method from new object and not allow create same name non-static method.I need to use same name method static and non-static.
Foo class has some default variables. I create new object and set default variables.
Sample code block
class Foo
{
public void abc()
{
//...
}
public static string xyz(string s)
{
return "bla bla";
}
}
public void btn1_click()
{
System.Windows.Forms.MessageBox.Show(Foo.xyz("value"));
//Works OK
}
public void btn1_click()
{
Foo f1=new Foo();
//f1..
f1.xyz("value");
//Cant access non static method.
}
Thanks in advance.
If the class has default values, the correct place to populate them is in the class constructor:
public class Foo
{
public Foo()
{
// set default values here.
}
}
If you still want to use these default values as static members - no problem:
public class Foo
{
public static const int DEFAULT_INT_VALUE = 5;
public Foo()
{
IntValue = DEFAULT_INT_VALUE;
}
public int IntValue {get;set;}
}
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));
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.