Accessing a public class member dynamically - c#

public class Names
{
private string _name1 = "";
private string _name2 = "";
private string _name3 = "";
public string Name1
{
get { return _name1; }
set { _name1 = value; }
}
public string Name2
{
get { return _name2; }
set { _name2 = value; }
}
public string Name3
{
get { return _name3; }
set { _name3 = value; }
}
}
collection Names = new Names();
I have a long string of text (longString). If the text at position 10 is 2, then I need to set values for two of the Names: Name1 and Name2. My variables are in a class that I have already instantialized. So I need to dynamically set the values of a dynamic number of variables. How do I call the variables and set the values dynamically? Basically something like this:
for (int i = 1; i <= collection.Count(); i++)
{
col.Name + i = longString.Substring(11, 4);
}

Try this:
public class Names
{
public string Name1 { get; set; }
public string Name2 { get; set; }
public string Name3 { get; set; }
}
for (int i = 1; i <= collection.Count(); i++)
{
var col = collection.ElementAt(i);
col.GetType().GetProperty("Name + i").SetValue(col, longString.Substring(11, 4), null);
}
Name1, Name2 and Name3 are auto-implemented properties. We're using reflection to get the properties by name and to set its values.

Faster than using reflection:
public class Names
{
private string[] _names = {"", "", ""};
public string[] Names { get {return _names; } } // ReadOnlyCollection?
public string Name1
{
get { return _names[0]; }
set { _names[0] = value; }
}
}

Related

Given list of classes, how to make list\array from specific property of class?

I have a class:
public class MyField
{
private string fieldName;
public string FieldName
{
get { return fieldName; }
set { fieldName = value; }
}
private string fieldValue;
public string FieldValue
{
get { return fieldValue; }
set { fieldValue = value; }
}
private string fieldValidation;
public string FieldValidation
{
get { return fieldValidation; }
set { fieldValidation = value; }
}
private bool fieldValid;
public bool FieldValid
{
get { return fieldValid; }
set { fieldValid = value; }
}
}
and then I have a list made of them:
private IList<MyField> myFields;
myFields = new List<SpectraNameField>()
{
new SpectraNameField{FieldName = "FirstField", FieldValue="", FieldValid = false, FieldValidation="" },
new SpectraNameField{FieldName = "SecondField", FieldValue="", FieldValid = false, FieldValidation="" }
};
I then populate FieldValue for each member of the list through my XAML, but let's say as an example I just say:
myFields[0].FieldValue = "Value0";
myFields[1].FieldValue = "Value1";
At the end I need to get all the values of FieldValue for each MyField joined using "_" (i.e. I need to get string "Value0_Value1")
How do I get list or array of all the FieldValue of my list of MyField?
Use .Selectto get the values
var fieldValues = myFields.Select(f => f.FieldValue);
Use string.Join to combine multiple strings
var joinedString = string.join("_", fieldValues);

how do you add get and set for an array in c#

I'm coding a func that inputs an array with different year of birth and prints out the oldest person.
I'm trying to add a validation with get and set but my syntax is wrong.
enter image description here
TL;DR
Properties declaration part:
public class Employee
{
private string _fullName;
private int _yearIn;
public string FullName
{
get => _fullName;
set
{
if (!string.IsNullOrEmpty(value))
{
_fullName = value;
}
}
}
public int YearIn
{
get => _yearIn;
set
{
if (value > 0 && value <= 2020)
{
_yearIn = YearIn;
}
}
}
}
And a usage:
var employees = new List<Employee>();
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Enter Name:");
string name = Console.ReadLine();
Console.WriteLine("Enter Year:");
int yearIn = Convert.ToInt32(Console.ReadLine());
employees.Add(new Employee
{
FullName = name,
YearIn = yearIn
});
}
Update
You can do the same in a bit different manner though:
public class Employee
{
private string _fullName;
private int _yearIn;
public bool IsNameValid { get; set; }
public bool IsYearValid { get; set; }
public string FullName
{
get => _fullName;
set
{
_fullName = value;
IsNameValid = string.IsNullOrEmpty(value);
}
}
public int YearIn
{
get => _yearIn;
set
{
_yearIn = value;
IsYearValid = (value < 0) || (value > 2020);
}
}
}
And later:
Console.WriteLine($"Employee name is: {employees[i].IsNameValid}");
Console.WriteLine($"Employee year is: {employees[i].IsYearValid}");
Update 2
And the last alternative version is that you can use Validation attributes:
public class Employee
{
[Required]
[Range(0, 2020)]
public int YearIn { get; set; }
[Required]
[StringLength(50)]
public string FullName { get; set; }
}
later:
var empl = new Employee{ YearIn = yearIn, FullName = name};
var context = new ValidationContext(empl, serviceProvider: null, items: null);
var results = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(empl, context, results, true);
Console.WriteLine($"Is model valid: {isValid}");
if (isValid)
{
employees.Add(new Employee
{
FullName = name,
YearIn = yearIn
});
}
You can create wrapper classes over array and use indexer method for accessing the array item.
There in, you can put all your validation logic.
class IntData
{
public IntData(int size)
{
data = new int[size];
}
// Array of temperature values
private int[] data;
public int this[int index]
{
get
{
return data[index];
}
set
{
// Do your validation here
if (value < 5000)
{
data[index] = value;
}
}
}
}
static void Main(string[] args)
{
IntData year = new IntData(3);
year[0] = 2000;
year[1] = 6000; // This value won't set because of validation
year[2] = 4000;
Console.Read();
}

c# how to give constructor fields from another class

I have 3 Classes : Masina (Car), Destinatie (Destination) and MasinaDestinatie (CarDestination).
I need the third class to get the values of the car number _nr_masina and the destination _cod_dest through it's own constructor.
I need to make a constructor with parameters in the third class that stores the values of _nr_masina and _cod_dest.
Anyone know how can i do this exactly? I've tried making the private fields public and putting them as parameters but that doesn't work...
The classes:
namespace Problema_test
{
class Masina
{
private string _nr_masina = string.Empty;
private string _valoare = string.Empty;
private string _an_fabricatie = string.Empty;
public Masina(string nr_masina,string valoare, string an_fabricatie)
{
_nr_masina = nr_masina;
_valoare = valoare;
_an_fabricatie = an_fabricatie;
}
public string Numar
{
get { return _nr_masina; }
set { _nr_masina = value; }
}
public string Valoare
{
get { return _valoare; }
set { _valoare = value; }
}
public string Anul
{
get { return _an_fabricatie; }
set { _an_fabricatie = value; }
}
}
class Destinatie
{
private string _cod_destinatie = string.Empty;
private string _adresa = string.Empty;
public Destinatie(string cod_destinatie, string adresa)
{
_cod_destinatie = cod_destinatie;
_adresa = adresa;
}
public string CodDest
{
get { return _cod_destinatie; }
set { _cod_destinatie = value; }
}
public string Adresa
{
get { return _adresa; }
set { _adresa = value; }
}
}
class MasinaDestinatie
{
// how can i make this work?
public MasinaDestinatie(string numarMasina, string codDest)
{
}
}
}
You can store the values inside properties
class MasinaDestinatie
{
public string Numar {get;set;}
public string CodDest {get;set;}
public MasinaDestinatie(string numarMasina, string codDest)
{
Numar = numarMasina;
CodDest = codDest;
}
}
To use the class you have do something like this
var masina = new Masina("Dacia","2000","1992");
var destinatie = new Destinatie("123", "Romania");
var masinaDestinatie = new MasinaDestinatie(masina.Numar, destinatie.CodDest);
Solution 2: As #blas-soriano sugested you can store the reference of the objects (Masina, Destinatie), this way you won't have problems (i.e. CodDest exist only in MasinaDestinatie but not in Destinatie, and many others).
class MasinaDestinatie
{
private Masina _masina {get;set;}
private Destinatie _destinatie {get;set;}
public string Numar { get { return _masina.Numar; } }
public string CodDest { get { return _destinatie.CodDest; } }
public MasinaDestinatie(Masina masina, Destinatie destinatie)
{
_masina = masina;
_destinatie = destinatie;
}
}
To use the class you have do something like this
var masina = new Masina("Dacia","2000","1992");
var destinatie = new Destinatie("123", "Romania");
var masinaDestinatie = new MasinaDestinatie(masina, destinatie);

set is throwing StackOverflowException C#

I am trying to get and send a list of this object to a text file. The text file is in the following format.
name,IDnumber,department,value
there are quite a few lines of this so i used a for to read them in.
This is the code for the read and write to the file.
public List<Employee> ReadFile(string fileName) {
StreamReader fileIn = new StreamReader(fileName);
fileIn = File.OpenText(fileName);
List<Employee> list = new List<Employee>();
string[] test;
string name;
string ID;
string dep;
string post;
while (!fileIn.EndOfStream || !File.Exists(fileName)) {
string inString = fileIn.ReadLine();
test = inString.Split('#');
name = test[0];
ID = test[1];
dep = test[2];
post = test[3];
Employee newEmp = new Employee(name, ID, dep, post);
list.Add(newEmp);
}
fileIn.Close();
return list;
}
public void WriteFile(List<Employee> outList, string file) {
StreamWriter writeOut = new StreamWriter(file);
for (int i = 0; i < outList.Count; i++) {
writeOut.WriteLine(outList[i].name + '#' + outList[i].IDnum + '#' + outList[i].department + '#' + outList[i].position);
}
writeOut.close();
}
This is the code for my class. The error is being thrown at the set.
public class Employee {
public string name { get { return name; } set { name = value; } }
public string IDnum { get { return IDnum; } set { IDnum = value; } }
public string department { get { return department; } set { department = value; } }
public string position { get { return position; } set { position = value; } }
public Employee() {
name = string.Empty;
IDnum = string.Empty;
department = string.Empty;
position = string.Empty;
}
public Employee(string newName, string newID) {
name = newName;
IDnum = newID;
department = string.Empty;
position = string.Empty;
}
public Employee(string newName, string newID, string newDep, string
newPost) {
name = newName;
IDnum = newID;
department = newPost;
position = newDep;
}
}
I am not sure if there is some kind of formatting that I am missing for the set function to function as needed. The This is the function i am calling for the in and out of the file. I believe that it is never making it to the out so it is likely how i am importing the data.
It's a really common gotcha... a C# rite of passage!
Let's take a look at a single property (this applies to all of your properties though)...
public string name { get { return name; } set { name = value; } }
so what happens when you try myObj.name = "foo";?
In the set method, you refer back to the very same property name. So it tries to access name, which goes around again (and again, and again, recursively until you StackOverflow).
A backing field with proper naming conventions is the norm here:
private string name;
public string Name{get { return name; } set{ name = value; }}
or even better, if there's no logic involved, an auto-property.
public string Name{ get; set; }
You keep calling IDnum and other properties over and over recursively, until the stack overflows
public string IDnum { get { return IDnum; } set { IDnum = value; } }
When you do something like
IDnum = someValue;
that calls the setter for IDnum, which runs the code in the setter
IDnum = value
Which in turn calls the setter of IDnum, until you run out of stack.
The Fix
In your case, it looks like you can use automatic properties
public string IDnum { get; set; }
You should change
public string name { get { return name; } set { name = value; } }
public string IDnum { get { return IDnum; } set { IDnum = value; } }
public string department { get { return department; } set { department = value; } }
public string position { get { return position; } set { position = value; } }
to
public string name { get; set; }
public string IDnum { get; set; }
public string department { get; set; }
public string position { get; set; }
or introduce backing fields:
private string _name;
public string name { get { return _name; } set { _name = value; } }
See https://msdn.microsoft.com/en-us/library/bb384054.aspx for more info on Auto-Implemented Properties in C#.
Please note, that the commonly used naming of public properties is PascalCasing. Your properties in PascalCasing would look like this:
public string Name { get; set; }
public string IdNum { get; set; }
public string Department { get; set; }
public string Position { get; set; }

Get the properties of objects in array

I have a small problem here.
I have an array which holds some objects (which have properties, duh)
Now I want to sort them by an int property that they have. My qustion is not how to sort them, but how do I read the value of the property of the objects in the array?
private void WriteHighscoreToFile(int groesse, int minenAnzahl, int zeit, string name)
{
using (StreamWriter sw = new StreamWriter(#"C:\Users\tstadler\Desktop\Highscore.txt", true))
{
sw.WriteLine("Spieler: " + name + " Punkte: " + (groesse * minenAnzahl - zeit * 2) + " Groesse: " + groesse + " Minenanzahl " + minenAnzahl + " Zeit: " + zeit);
}
using (StreamReader sr = new StreamReader(#"C:\Users\tstadler\Desktop\Highscore.txt", true))
{
List<CreateNewHighscore> highScores = new List<CreateNewHighscore>();
while (sr.ReadLine() != null)
{
_objectProperties = sr.ReadLine().Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
highScores.Add(new CreateNewHighscore(_objectProperties));
highscoreCount++;
}
_highscoresArray = highScores.ToArray();
vergleicheArray(_highscoresArray);
}
}
The Class:
public class CreateNewHighscore
{
public string _name;
public int _punkte;
public int _groesse;
public int _minenAnzahl;
public int _zeit;
public CreateNewHighscore(string[] infos)
{
_name = infos[1];
_punkte = int.Parse(infos[5]) * int.Parse(infos[7]) - 2 * int.Parse(infos[9]);
_groesse = int.Parse(infos[5]);
_minenAnzahl = int.Parse(infos[7]);
_zeit = int.Parse(infos[9]);
} }
My qustion is not how to sort them, but how do I read the value of the property of the objects in the array?
You expose it as a property; for example:
class CreateNewHighscore
{
string _name;
int _punkte, _groesse, _minenAnzahl, _zeit;
public string Name { get { return _name; } }
public int Punkte { get { return _punkte; } }
public int Groesse { get { return _groesse; } }
public int Zeit { get { return _zeit; } }
public int MinenAnzahl { get { return _minenAnzahl; } }
// constructor not shown
}
Then you can access that member from any array / list; for example:
highScores.Sort((x,y) => x.Punkte.CompareTo(y.Punkte));
or:
int firstPunkte = _highscoresArray[0].Punkte;
Your array is of type CreateNewHighscore[] so if you want to access property in classic way just use following line.
_highscoresArray[i].YourIntProperty
where "YourIntProperty" is desired int property.
Use LINQ OrderBy method:
_highscoresArray = highScores.OrderBy(h => h.Punkte).ToArray();
Where Punkte is a property of your CreateNewHighscore class:
public int _punkte; // public field
public Punkte // public property
{
get { return _punkte; }
set { _punkte = value; } // you may not need setter
}
BTW currently your class DO NOT have any properties. There are only public (after your last edit) fields. If you want to sort by field value then:
_highscoresArray = highScores.OrderBy(h => h._punkte).ToArray();
But I advice you to make fields private, or use auto implemented properties instead. And rename your class. Name is really awful and sounds like method name.
public class CreateNewHighscore
{
public string Name { get; private set; }
public int Punkte { get; private set; }
public int Groesse { get; private set; }
public int MinenAnzahl { get; private set; }
public int Zeit { get; private set; }
public CreateNewHighscore(string[] infos)
{
// check infos count
Name = infos[1];
Punkte = int.Parse(infos[5]) * int.Parse(infos[7]) -
2 * int.Parse(infos[9]);
Groesse = int.Parse(infos[5]);
MinenAnzahl = int.Parse(infos[7]);
Zeit = int.Parse(infos[9]);
}
}

Categories

Resources