In a class I have declared one property like below
class MyClass
{
public string TName
{
get {return "";}
}
// and some other properties ....
}
One method is returning the type IEnumerable<MyClass>, here I want to get the TName value as
Name 1, Name 2, Name 3, Name 4........
based on the count.
Problem:
How can I increment the value of counter in my setter method of the above property, so that i can append like "Name" + counter;
Or is there any other better way to achieve this without looping and fetching the count from DB.
Thank you in advance.
Same idea (we have a counter s_Count) but in case you want it thread safe we have to increment it in a special way:
class MyClass {
private static int s_Count;
public string TName {
get;
}
public MyClass() {
TName = $"Name {Interlocked.Increment(ref s_Count)}";
}
}
You need a static counter within MyClass that contains the number of instances that were already created:
class MyClass
{
static int count = 0;
public MyClass() { count++; }
}
Now you can easily access that counter within your Name-property:
string Name { get => $"Name{ counter }"; }
If there are multple threads that may concurrently increment the counter it´s better to use Interlocked.Increment(ref count) instead of count++ within the constructor.
you'll need to store the value of TName in a private string;
private string m_TName;
public string TName
{
get {return m_TName + counter;}
set {
if (m_TName != value){
m_TName = value
}
}
}
if TName is always the same you can use
private string m_TName = "Default value";
public string TName
{
get {return m_TName + counter;}
}
if you want to increment the counter each call
private string m_TName = "Default value";
public string TName
{
get {
counter++;
return m_TName + counter;
}
}
if you want it on every instance as per HimBromBeere's comment
private string m_TName;
public string TName
{
get {return m_TName;}
set {
if (m_TName != value){
counter++;
m_TName = value + counter;
}
}
}
if you want it on every instance as per HimBromBeere's comment AND you only want to set it once
private string m_TName;
public string TName
{
get {return m_TName;}
set {
if (m_TName != value && m_TName == null){
counter++;
m_TName = value + counter;
}
}
}
Related
I have the following C# class with a property Id which I would like to set with a GUID and return if the consumer calls the value of an instance of myClass.Id for which this value has not yet been set, but otherwise to keep and return the existing value.
public class IdentifiableClass{
public string Id {
get {
if (this.Id == null) {
this.Id = Guid.NewGuid().ToString();
Console.WriteLine("########## Id : " + this.Id );
}
return this.Id;
}
set => this.Id = value;
}
}
In C#, this does not work, but rather I get a stackoverflow (not this site, obviously).
Best guess, invoking this.Id within the same property's getter seems to resulting in circular logic.
In Salesforce Apex, with this similar code, it does work as I would expect it to, evaluating the value of this.Id as null, assigning the value to the new Guid, displaying the value, and then returning the value:
public class IdentifiableClass {
public string Id {
get {
if (this.Id == null) {
this.Id = String.valueOf(Integer.valueof((Math.random() * 10)));
System.debug('########## Id : ' + this.Id );
}
return this.Id;
}
set;
}
}
Is it possible to make this work in C#?
If so, how?
Probably you should create full property with private field.
public class IdentifiableClass{
private string id;
public string Id {
get {
if (this.id == null) {
this.id = Guid.NewGuid().ToString();
Console.WriteLine("########## Id : " + this.id );
}
return this.id;
}
set => this.id = value;
}
}
What you need to do is not to use auto-property feature.
You should put explicitly private string _id; field and your getters and setters should internaly use that
I have an issue with my application.
Using the debugger I've found that my application is stuck in an infinite loop. I have attached an image to demonstrate the error which occurs when I try to execute the program.
When executed
However, when debugging I've come to the conclusion this is an issue with either my CompareTomethod or my InsertItem method in my AVLTree class.
The program appears to loop around the following line of codes-
In my Country class-
public int CompareTo(object obj)
{
Country temp = (Country)obj;
return name.CompareTo(temp.name);
}
And in my AVLTree class (doesn't go past the code I have attached)-
private void insertItem(T item, ref Node<T> tree)
{
if (tree == null)
{
tree = new Node<T>(item);
}
else if (item.CompareTo(tree.Data) < 0)
{
insertItem(item, ref tree.Left);
}
I am reading in data from a CSV file, however, this occurs when the application reads in the fourth entry in the CSV File.
I can insert the following countries - USA, Canada, Brazil but Chile (the next record) appears to run into this issue. I was wondering what the problem could be?
I am inserting this data with this piece of code:
avlTree.InsertItem(new Country(columns[0], float.Parse(columns[1]), float.Parse(columns[2]), float.Parse(columns[3]), Int32.Parse(columns[4]), tradingPartners));
I have the loop to get the trading partners and the code to read in the file as well, just cannot seem to get out of this loop. Where could the issue lie?
I have the following classes-
AVLTree
BSTree
BinTree
Country
Node
Form
Program
Thank you for your time.
UPDATE - My whole Country class where my CompareTo method is-
private string name;
private float GDP;
private float inflation;
private float tradeBal;
private int HDI;
public LinkedList<String> tradingPartners;
public string x;
public Country()
{
}
public Country(string name, float GDP, float inflation, float tradeBal, int HDI, LinkedList<String> tradingPartners)
{
this.name = name;
this.GDP = GDP;
this.inflation = inflation;
this.tradeBal = tradeBal;
this.HDI = HDI;
this.tradingPartners = tradingPartners;
}
public string CountryName
{
get { return name; }
set { name = value; }
}
public float GDPGrowth
{
get { return GDP; }
set { GDP = value; }
}
public float Inflation
{
get { return inflation; }
set { inflation = value; }
}
public float TradeBalance
{
get { return tradeBal; }
set { tradeBal = value; }
}
public int HDIRank
{
get { return HDI; }
set { HDI = value; }
}
public LinkedList<String> TradingPartners
{
get { return tradingPartners; }
set { tradingPartners = value; }
}
public int CompareTo(object obj)
{
Country temp = (Country)obj;
return name.CompareTo(temp.name);
}
public override string ToString()
{
foreach (string y in TradingPartners)
{
x += y + ", ";
}
return name + ". " + GDP + ", " + inflation + ", " + tradeBal + ", " + HDI + "[ " + x + " ]";
}
I hope this can be of help, I don't think it's my AVLTree as I used to once before and no issues arised. I forgot to add, the code continuously loops back and forth between my CompareTo and my insertItem method (up to where I've pasted it in, will not go further than that).
I am relatively new to C# (WinForms), and had a question regarding combo boxes. I have a combo box of Reviewer objects (it is a custom class with an overridden ToString method) and am currently attempting to go through all the checked items and use them to generate a setup file.
Here is how the combo box is populated (populated on form load). Parameters is just a collection of linked lists and parsing code.
for (int i = 0; i < parameters.GetUsers().Count; i++)
{
UserList.Items.Add(parameters.GetUsersArray()[i], parameters.GetUsersArray()[i].isSelected());
}
Here is how I am trying to read it. setup is a StringBuilder. The problem is that GetID is not defined. Does the add function above cast the Reviewer object to a Object object? It looks a little funny since it creates a file fed into a Perl script. A sample desired output line looks like this: inspector0 => "chg0306",
for (int i = 0; i < UserList.CheckedItems.Count; i++)
{
setup.AppendLine("inspector" + i.ToString() + " => \t \"" +
UserList.CheckedItems[i].GetID() + "\",");
}
Here is the users class: (Sample User is ID = aaa0000 name: Bob Joe)
public class Reviewer
{
private string name;
private string id;
private bool selected;
public Reviewer(string newName, string newID, bool newSelected)
{
name = newName;
id = newID;
selected = newSelected;
}
public string GetName()
{
return name;
}
public override string ToString()
{
//string retVal = new string(' ', id.Length + name.Length + 1);
string retVal = id + '\t' + name;
return retVal;
}
public string GetID()
{
return id;
}
public bool isSelected()
{
return selected;
}
}
For posterity, here is the Parameters class:
public class ParameterLists
{
public ParameterLists()
{
projects = new LinkedList<string>();
reviewers = new LinkedList<Reviewer>();
}
public enum FileContents {
PROJECT_LIST,
USERS_LIST,
}
public LinkedList<Reviewer> GetUsers()
{
return reviewers;
}
public LinkedList<string> GetProjects()
{
return projects;
}
public Reviewer[] GetUsersArray()
{
Reviewer[] userArray = new Reviewer[reviewers.Count];
reviewers.CopyTo(userArray, 0);
return userArray;
}
public string[] GetProjectsArray()
{
String[] projectArray = new String[projects.Count];
projects.CopyTo(projectArray, 0);
return projectArray;
}
public void LoadParameters(string fileName)
{
//Reads the parameters from the input file.
}
private void CreateDefaultFile(string fileName)
{
// Create the file from the defaultfile , if it exists.
// Otherwise create a blank default file.
}
private LinkedList <string> projects;
private LinkedList <Reviewer> reviewers;
}
I am probably missing something simple, coming from embedded C++. Any help would be appreciated.
You have to cast that object:
((Reviewer)UserList.CheckedItems[i]).GetID()
I am trying to add a helper method to scrub out any non-alphanumeric characters in my class. However, I keep getting the error
NullReferenceException: Object reference not set to an instance of an object.
Not sure what I'm doing wrong here since I thought this was the proper way to set up any kind of validation within a class. Any suggestions would be appreciated.
private string agentId;
public string AgentId
{
get { return agentId; }
set { agentId = this.scrubAgentId(); }
}
private string scrubAgentId()
{
char[] arr = this.AgentId.ToCharArray();
arr = Array.FindAll<char>(arr, (c => (char.IsLetterOrDigit(c))));
return new string(arr);
}
This isn't really right at all. You're discarding the value when performing your set. It should probably look something more like this:
private string agentId;
public string AgentId
{
get { return agentId; }
set { agentId = this.scrubAgentId(value); }
}
private string scrubAgentId(string value)
{
if(value == null)
return value;
char[] arr = value.ToCharArray();
arr = Array.FindAll<char>(arr, (c => (char.IsLetterOrDigit(c))));
return new string(arr);
}
In the set part of the property you have an implicit object, value which holds the value you want to set... Use this value as your base
private string agentId;
public string AgentId
{
get { return agentId; }
set { agentId = value; } // manipulate value here using your method
}
Are you initialising agentid anywhere first?
Its failing on char[] arr = this.AgentId.ToCharArray();
You never reference the value in your setter. You want to do something like this:
private string agentId;
public string AgentId
{
get
{
return agentId ;
}
set
{
agentId = new string( value.ToCharArray().Where( c => c.IsLetterOrDigit(c) ) ) ;
}
}
I have the following class:
public class test
{
private int i;
public test(int in)
{
i = in;
}
public int testint;
{
get { return i; }
set { i = testint; }
}
}
And the following code:
test[] data = new test[3];
for(int j = 0; j < 3; j++)
{
data[i] = new test(0);
data[i].testint = int.Parse(Console.ReadLine());
}
Console.WriteLine(test[0].testint);
Console.WriteLine(test[1].testint);
Console.WriteLine(test[2].testint);
When I run this program and type in 1, 2, 3 as the input, the output is 0, 0, 0. I don't understand why the get or set seem to be not working. If I initialize the array elements with a value other than 0, the output will be that. The data[i].testint = int.Parse(Console.ReadLine()); seems to not be working. How would I go about doing something like that?
Change the set method to this:
public int testint
{
get { return i; }
set { i = value; }
}
You setter is incorrect. It should be:
set { i = value; }
You had:
set { i = testint; }
Which only triggers the getter, which gets from i, so in the end your setter was doing i = i .
In a setter, the value keyword contains the new candidate value for the property. value's type equals the property's. I say candidate value because you can validate it and choose to not apply it.
In your case, you were not applying the value.
Update
Also, when defining getters and setters, no semicolon should be used. Code, then, would look like this:
public int testint
{
get { return i; }
set { i = value; }
}
I see two errors in this code:
public int testint;
{
get { return i; }
set { i = testint; }
}
There should be no semicolon after testint at the top. Also, set needs to assign using value, like this:
public int testint
{
get { return i; }
set { i = value; }
}
Change your setter to say:
set { i = value; }
value corresponds to the value you send to set the variable.
Here's simple way.
public int TestInt {get; set;}