Get the properties of objects in array - c#

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]);
}
}

Related

Method for showing list elements

I have list in class
public List<Igrac> Igraci { get; set; } = new List<Igrac>();
The class:
class Igrac
{
public string Ime { get; set; }
public string Prezime { get; set; }
public string Pozicija { get; set; }
public int Godine { get; set; }
public Igrac(string Ime, string Prezime, string Pozicija, int Godine)
{
this.Ime = Ime;
this.Prezime = Prezime;
this.Pozicija = Pozicija;
this.Godine = Godine;
}
}
Added new list elements:
noviklb.DodavanjeIgraca(new Igrac("Petar", "Petrovic", "Krilo", 1992));
noviklb.DodavanjeIgraca(new Igrac("Badr", "Hari", "Napad", 1993));
The method for adding is working OK. The problem is that when I use Console.WriteLine I get an error like this:
System.Collections.Generic.List`1[zadatak.Program+Igrac]
I Googled and foreach is solution but I cant do it right. Do I need to write foreach as method?
class Igrac
{
public string Ime { get; }
public string Prezime { get; }
public string Pozicija { get; }
public int Godine { get; }
public Igrac(string Ime, string Prezime, string Pozicija, int Godine)
{
this.Ime = Ime;
this.Prezime = Prezime;
this.Pozicija = Pozicija;
this.Godine = Godine;
}
}
public override string ToString()
{
return $"{Ime} {Prezime} {Pozicija} {Godine}";
}
Now you can use.
string myStringDate = new Igrac("Petar", "Petrovic", "Krilo", 1992).ToString();
ALSO NOTE: It would be good to make you properties get only.
Working link:
https://dotnetfiddle.net/zMNiln
use this code:
public void showList(List<Igrac> noviklb)
{
foreach (var item in noviklb)
{
Console.WriteLine("Ime : " + item.Ime);
Console.WriteLine("Prezime : " + item.Prezime);
Console.WriteLine("Pozicija : " + item.Pozicija);
Console.WriteLine("Godine : " + item.Godine);
Console.WriteLine("Get New Record****************** ");
}
}

Creating two C# class definitions with a driver to test classes, but not sure why so many errors?

I am new to C# and was asked to create two class definitions (customer and order) using partial code and with the suggested class names, methods, contructors and following an example. I am not sure why I am getting so many errors when I build/debug?
After this is finished, I need to create another program that builds onto this one. Our instructor also asked us not to use validation...
Some of my most common errors are:
expected: ; (in a place in my code where I believe there should not be a semi-colon and
Error "Expected class, delegate, enum, interface, or struct.
Here is my code:
public class clsOrder
{
//declare class variables
protected string cstrDescription;
protected int cintQuantity;
protected decimal cdecPrice;
protected decimal cdecExtendedPrice;
//shared variables
static decimal cdecTotalPrice;
static int cintTotalCount;
//declare constructors
public clsOrder();
}
public clsOrde r(string strDescription,
int intQuantity, decimal decPrice)
}
//declare property methods
{
this.Description = string strDescription;
this.Quantity = int intQuantity;
this.Price = decimal decPrice;
//declare read-only properties
public decimal ExtendedPrice
}
public string Description
{
get
{
return strDescription;
}
set
{
strDescription = value;
}
}
public int Quantity
{
get
{
return intQuantity;
}
set
{
intQuantity = value;
}
}
public decimal Price
{
get
{
return decPrice;
}
set
{
decPrice = value;
}
}
get
{
return cdecExtendedPrice;
}
}
//declare Shared (static) ReadOnly Properites
public static decimal TotalPrice
{
get
{
return cdecTotalPrice;
}
}
public static int TotalCount
{
get
{
return cintTotalCount;
}
}
//declare supporting methods
public void calcExtendedPrice()
{
cdecExtendedPrice = cintQuantity * cdecPrice;
}
public void accumulateTotals()
{
cdecTotalPrice += cdecExtendedPrice;
cintTotalCount += 1;
}
public static void resetTotals()
{
cdecTotalPrice = 0;
cintTotalCount = 0;
}
}//end of Class
}//end of namespace
And
public class clsCustomer
{
//declare class variables
private string cstrName;
private string cstrStreet;
private string cstrCity;
private string cstrState;
private string cstrZip;
//declare constructors
public class clsCustomer()
}
public clsCustomer(string strName,
string strStreet, string strCity,
string strState, string strZip)
}
//declare property methods
{
this.Name = cstrName;
this.Street = cstrStreet;
this.City = cstrCity;
this.State = cstrState;
this.Zip = cstrZip;
}
public string Name
{
get
{
return cstrName;
}
set
{
cstrName = value;
}
}
public string Street
{
get
{
return cstrStreet;
}
set
{
cstrStreet = value;
}
}
public string City
{
get
{
return cstrCity;
}
set
{
cstrCity = value;
}
}
public string State
{
get
{
return cstrState;
}
set
{
cstrState = value;
}
}
public string Zip
{
get
{
return cstrZip;
}
set
{
cstringZip = value;
}
}
Any help would be very much appreciated, thank you.

linq update not working

I have tried a lot but all in vain.
I have written a LINQ code but not able to save changes in database.
It is giving no error neither it is updating record.
class Program
{
[Table(Name = "mainframe_replication")]
public class mainframe_replication
{
private string _REPL_GUID;
[Column(IsPrimaryKey = true, Storage = "_REPL_GUID")]
public string REPL_GUID
{
get { return this._REPL_GUID; }
set { this._REPL_GUID = value; }
}
private string _REPL_TYPE;
[Column(Storage = "_REPL_TYPE")]
public string REPL_TYPE
{
get { return this._REPL_TYPE; }
set { this._REPL_TYPE = value; }
}
private string _RPT_ID;
[Column(Storage = "_RPT_ID")]
public string RPT_ID
{
get { return this._RPT_ID; }
set { this._RPT_ID = value; }
}
private string _RPT_VERS;
[Column(Storage = "_RPT_VERS")]
public string RPT_VERS
{
get { return this._RPT_VERS; }
set { this._RPT_VERS = value; }
}
private string _RPT_BYTES;
[Column(Storage = "_RPT_BYTES")]
public string RPT_BYTES
{
get { return this._RPT_BYTES; }
set { this._RPT_BYTES = value; }
}
private string _REPL_DTM;
[Column(Storage = "_REPL_DTM")]
public string REPL_DTM
{
get { return this._REPL_DTM; }
set { this._REPL_DTM = value; }
}
private string _NOTIF_ID;
[Column(Storage = "_NOTIF_ID")]
public string NOTIF_ID
{
get { return this._NOTIF_ID; }
set { this._NOTIF_ID = value; }
}
}
public class MyPoco
{
public string ReportId { get; set; }
public string Reportversion { get; set; }
public string ReportBytes { get; set; }
public string ReportDate { get; set; }
public string NotifId { get; set; }
public string RecipAdd { get; set; }
}
public static string loglocation;
static void Main(string[] args)
{
try
{
using (DataClasses1DataContext db = new DataClasses1DataContext())
{
Table<NOTIF_RECIP> NOTIF_RECIP_alias = db.GetTable<NOTIF_RECIP>();
Table<NOTIF_SCHED> NOTIF_SCHED_alias = db.GetTable<NOTIF_SCHED>();
Table<mainframe_replication> mainframe_replication_alias = db.GetTable<mainframe_replication>();
var ids = NOTIF_SCHED_alias.Select(x => x.NOTIF_RPT_ID).ToArray();
foreach (string notif_sched_data in ids)
{
var repljoinmf = mainframe_replication_alias
.Join(NOTIF_RECIP_alias, mfr => mfr.RPT_ID, nr => nr.NOTIF_RECIP_ID, (mfr, nr)
=> new MyPoco { ReportId = mfr.RPT_ID, Reportversion = mfr.RPT_VERS, ReportBytes = mfr.RPT_BYTES.ToString(), ReportDate = mfr.REPL_DTM.ToString(), NotifId = mfr.NOTIF_ID, RecipAdd = nr.NOTIF_RECIP_ADDR });
foreach (var repljoinmf_data in repljoinmf)
{
repljoinmf_data.NotifId = "abc";
//DO STUFF
// repljoinmf_data.NotifId = "Changedxyz";
}
db.SubmitChanges();
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
It is not giving any error while submitting changes.
What I need to change?
Any suggestion will be helpful.
If you want to save your changes back to the original data source, you need to be working with the actual entities instead of projections of those entities. Since you are joining two tables, one option is to put those instances into an anonymous type and update them:
foreach (string notif_sched_data in ids)
{
var repljoinmf = mainframe_replication_alias
.Join(NOTIF_RECIP_alias,
mfr => mfr.RPT_ID,
nr => nr.NOTIF_RECIP_ID,
(mfr, nr) => new {mfr, nr});
foreach (var repljoinmf_data in repljoinmf)
{
//DO STUFF
repljoinmf_data.mfr.NotifId = "Changedxyz";
}
db.SubmitChanges();
In your previous question you were told that anonymous types cannot be uptated, but in this case you're modifying instances that are referenced by the anonymous type. So you're not updating the anonymous type itself, just the objects that the anonymous type references.
You are modifying the property of your MyPoco object. This is just a representation of your table. That's why the database is not updated.
You can send your MyPoco to your client. It will perform some changes. Then you can recreate the entity and copy the properties from the Poco object. Then, you need to attach the modified entity to your table and then save the changes.
If you modify directly the entity, there is no need to attach, since it will have kept the links to the database (assuming you do that with the same Databasecontext).

Accessing a public class member dynamically

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; }
}
}

Stackoverflow error C# with getter and setter

This is the working class:
namespace Lite
{
public class Spec
{
public int ID { get; set; }
public string Name { get; set; }
public string FriendlyName { get; set; }
public int CategoryID { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public string UOM { get; set; }
public int Pagination { get; set; }
public int ColoursFront { get; set; }
public int ColoursBack { get; set; }
public string Material { get; set; }
public int GSM { get; set; }
public string GSMUOM { get; set; }
public bool Seal { get; set; }
public Spec(int ID)
{
using (CrystalCommon.MainContext db = new CrystalCommon.MainContext())
{
var q = (from c in db.tblSpecifications where c.id == ID select c).SingleOrDefault();
if (q != null)
loadByRec(q);
}
}
public Spec(CrystalCommon.tblSpecification Rec)
{
loadByRec(Rec);
}
public void loadByRec(CrystalCommon.tblSpecification Rec)
{
this.ID = Rec.id;
this.Name = Rec.Title;
this.Width = Convert.ToInt32(Rec.FinishedSizeW.Value);
this.Height = Convert.ToInt32(Rec.FinishedSizeL.Value);
this.UOM = Rec.FlatSizeUOM;
this.Pagination = Rec.TxtPagination.Value;
this.ColoursFront = Convert.ToInt32(Rec.TxtColsF.Value);
this.ColoursBack = Convert.ToInt32(Rec.TxtColsB.Value);
this.Material = Rec.TxtMaterial;
this.GSM = Rec.TxtGSM.Value;
this.GSMUOM = Rec.txtGsmUnit;
this.Seal = Rec.TxtSeal.Value == 1;
}
public string displayDimensions()
{
return Width + " x " + Height + " " + UOM;
}
}
}
Then I try and modify the Name getter and setter:
namespace Lite
{
public class Spec
{
public int ID { get; set; }
// User friendly name if available otherwise fall back on spec name
public string Name { get {
if (null != FriendlyName)
return FriendlyName;
else
return Name;
}
set
{
Name = value;
}
}
public string FriendlyName { get; set; }
public int CategoryID { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public string UOM { get; set; }
public int Pagination { get; set; }
public int ColoursFront { get; set; }
public int ColoursBack { get; set; }
public string Material { get; set; }
public int GSM { get; set; }
public string GSMUOM { get; set; }
public bool Seal { get; set; }
public Spec(int ID)
{
using (CrystalCommon.MainContext db = new CrystalCommon.MainContext())
{
var q = (from c in db.tblSpecifications where c.id == ID select c).SingleOrDefault();
if (q != null)
loadByRec(q);
}
}
public Spec(CrystalCommon.tblSpecification Rec)
{
loadByRec(Rec);
}
public void loadByRec(CrystalCommon.tblSpecification Rec)
{
this.ID = Rec.id;
this.Name = Rec.Title;
this.Width = Convert.ToInt32(Rec.FinishedSizeW.Value);
this.Height = Convert.ToInt32(Rec.FinishedSizeL.Value);
this.UOM = Rec.FlatSizeUOM;
this.Pagination = Rec.TxtPagination.Value;
this.ColoursFront = Convert.ToInt32(Rec.TxtColsF.Value);
this.ColoursBack = Convert.ToInt32(Rec.TxtColsB.Value);
this.Material = Rec.TxtMaterial;
this.GSM = Rec.TxtGSM.Value;
this.GSMUOM = Rec.txtGsmUnit;
this.Seal = Rec.TxtSeal.Value == 1;
}
public string displayDimensions()
{
return Width + " x " + Height + " " + UOM;
}
}
}
On my computer this compiles fine, but the server seems to crash when it runs. (First version works fine). My colleague compiled it on his machine and it threw a "Stack overflow error" apparently, but he's not around for me to get specifics on that right now.
Am I applying the getter correctly here?
This is an endless loop:
public string Name { get {
...
set
{
Name = value;
}
}
The setter will call itself repeatedly until you get the Stack overflow exception.
usually you have a backing variable, so it ends up like this
private string name;
public string Name {
get {
if (null != FriendlyName)
return FriendlyName;
else
return name;
}
set {
name = value;
}
}
Your set is referencing the property itself, and your get is referencing the property itself, both of these will cause a potentially endless loop leading to a StackOverflowException (no more stack space to push the current call into). You need to use a backing field:
private string _name;
public string Name
{
get
{
if (null != FriendlyName)
return FriendlyName;
else
return _name;
}
set
{
_name = value;
}
}
It looks as though you tried to turn an auto-property into a manual one. Auto-properties (public string Name { get; set; }) work because the compiler will create the backing field itself.
As a learning exercise, if you step through with the debugger and step into return Name or Name = value you will see first hand the code going back into the property you are already in.
This is much better.
string _name = "";
public string Name
{
get { return FriendlyName ?? _name; }
set { _name = value; }
}
One of your properties gets and sets itself, see:
public string Name
{
get {
if (null != FriendlyName)
return FriendlyName;
else
return Name; //<-- StackOverflow
}
set
{
Name = value; //<-- StackOverflow
}
}
You have a getter for Name, that calls the property Name, which will call the getter for Name, etc. You need a private field to back the property, and you need to access that backing field in your getter instead.
public string Name { get {
if (null != FriendlyName)
return FriendlyName;
else
return Name;
}
set
{
Name = value;
}
}
Name in the get/set refers to the property. You will need to define a backing field and use that.
If FriendlyName is null then the Name getter attempts to get the value from the Name getter - i.e. it loops. This is what causes the stack overflow.
No you should use a backing field. The error is in the else
public string Name { get {
if (null != FriendlyName)
return FriendlyName;
else
return Name;//error, you're calling the property getter again.
}

Categories

Resources