C# code effectiveness - calling a property tens of times - c#

IDE: Visual Studio 2015 Update 3
Language: C# / .NET 4.5
Situation: Suppose I defined a class and I'm calling its properties tens of times, further let's suppose the class operates over one input given to the constructor and therefore it makes all operations except the first one redundant, because we already managed to calculate the return value the first time we called it.
Example of such property:
// let's call it a Month, because it extracts a month code from a string
private int Month
{
// there is only a getter
get
{
// here's my current strategy
// in the beginning of the class I set fMonth to -1
// it can only have possitive numbers, so if already set, I return it
if (fMonth > -1)
return fMonth;
// and here's the part I don't want to repeat
return fMonth =
Convert.ToInt32(SomeNumberString.Substring(2, 2));
}
}
Question: Is this the right strategy for not repeating the executive code?

Since the value for someNumberString is given to you in the constructor, you can use a readonly property.
ctor(string someNumberString)
{
Month = Convert.ToInt32(someNumberString.Substring(2, 2));
}
public Month { get; }

You are on the right track with using a private backing field fmonth for the property. You can further optimize this by moving the conversion code to an explicit set method. This removes the if check from every get access.
ctor(string someNumberString) {
SetMonth(someNumberString);
}
private int Month { get { return fmonth; } }
// -1 indicates that SetMonth() has never been called
private int fmonth = -1;
public void SetMonth(string someNumberString) {
fmonth = Convert.ToInt32(someNumberString.Substring(2, 2));
}

Related

Method parameter not being recognized [duplicate]

This question already has an answer here:
c# calling method with array parameters [closed]
(1 answer)
Closed 1 year ago.
My code looks like this:
void Update()
{
if (Input.GetKeyDown(KeyCode.G) && questCount == 6)
{
Score(sumFinal);
}
}
public int Score(int sumFinal)
{
sumFinal = dCount - rCount;
return sumFinal;
}
Visual Studio tells me sumFinal doesn't exist in the current context.
How can I return sumFinal within Update() successfully? Am I understanding parameters correctly?
Additional Question:
Below further down the Score() function, I set text to certain values:
public int Score(int sumFinal)
{
sumFinal = dCount - rCount;
return sumFinal;
if (sumFinal == 5 && questCount >= 5)
{
labelText.text = "results";
}
}
When calling this function in Update(), is there a way I can run both the if statement and the sumFinal subtraction equation separately? In short, how do I segment the function, and call only specific parts of it? Should the return type be set to void?
Visual Studio tells me sumFinal doesn't exist in the current context. How can I return sumFinal within Update() successfully? Am I understanding parameters correctly?
The method Score looks great! However, when you call it Score(sumFinal); you need to make sure that you're passing a value to the method. In your case you may have forgotten to have a field with the value at the top of the class.
is there a way I can run both the if statement and the sumFinal subtraction equation separately?
Sure! What you could do, since you don't actually give Score any value when you call it, you can remove that parameter and just return the value that it calculates.
The we could separate updating the text to another method called UpdateTextBox() that takes the result of Score() to determine if it should change the text or not
public class YourUnityClass : MOnoBehaviour
{
int questCount = 0;
int sumFinal = 0; // make sure that if you need to access this variable between methods that this field exists
int dCount = 0;
int rCount = 0;
public TextMesh labelText;
void Update()
{
if (Input.GetKeyDown(KeyCode.G) && questCount == 6)
{
// calculate and save the score
sumFinal = Score();
// check the score, and update the text if necessary
UpdateTextBox(sumFinal);
}
}
public int Score()
{
// calculate the score
return dCount - rCount;
}
public void UpdateTextBox(int sumFinal)
{
// check to see if the score is high enough to change
// the text
if (sumFinal == 5 && questCount >= 5)
{
labelText.text = "results";
}
}
}

Should the value of a property be updated with a method or determined in the getter?

Just a quick question so as to know if there is a better practice between updating the value of a property with a method that gets called everytime the value needs to be changed or just to do it in the getter.
For instance between this:
public double Balance { get; private set; }
private void UpdateBalance()
{
if (Payments.IsNullOrEmpty())
{
Balance = 0;
}
else
{
double amountSum = 0;
foreach (Payment payment in Payments)
{
amountSum += payment.Amount;
}
Balance = amountSum;
}
}
And this :
public double OtherBalance
{
get
{
if (Payments.IsNullOrEmpty())
return 0;
double amountSum = 0;
foreach (Payment payment in Payments)
{
amountSum += payment.Amount;
}
return amountSum;
}
}
The only difference I can think of is one of performance, since in the first case the getter runs through the whole list every time we try to get the value of the property. However, you don't need to worry about calling the Update method every time you do a change that might impact the value of the property like in the second option. Is that difference really significant ? Beyond that, is there any reason to chose one option over another ?
Thanks in advance
Well in first method for reading the balance you should call the getter again and in the second method there is no balance at all, personally I prefer second method because it's generate the value at the call time so you can be sure that it is always updated and it doesn't need to call a function and then read the value so it's cleaner and more maintainable.
To add to Kiani's answer, if you don't mind using Linq, you could turn your code to a one liner.
private double Balance=>(!Payments.Any())?0:Payments.Sum(t=>t.Amount);

How can i call upon only the return variable in a method?

I'm new and struggling with object orientated programming. I want to use only the return value in my third method 'tableinfo' however i don't know how to transfer only this value to the other methods, without running the first two methods again. All i want to do is transfer only the value that the user enters over to the third method and not have to put in the values two times each, this is the only way i know to get the value across and i would really appreciate if anyone could help me to just get the return value. This code is a tiny snippet of what i'm trying to do and it's purpose is not important, i just wanted to create an example to try and allow people to understand what i mean.
Thank you in advance!
class Program
{
static void Main(string[] args)
{
TableOrder TO = new TableOrder();
TO.TableNumber();
TO.NumberOfPartons();
TO.tableinfo();
}
}
class TableOrder
{
int tablenumber;
string inputtablenumber;
int numberAtTable;
string inputNumberAtTable;
public int TableNumber()
{
Console.Write("please enter the table number:");
inputtablenumber = Console.ReadLine();
tablenumber = int.Parse(inputtablenumber);
return tablenumber;
}
public int NumberOfPartons()
{
Console.Write("please enter how many people are seated: ");
inputNumberAtTable = Console.ReadLine();
numberAtTable = int.Parse(inputNumberAtTable);
return numberAtTable;
}
public void tableinfo()
{
int tablenum = TableNumber();
Console.Write(tablenumber + 1);
int patrons = NumberOfPartons();
Console.WriteLine(numberAtTable + 1);
}
}
It looks like you might be confused on the difference between methods, properties, and fields. Your function TableNumber() might be more accurately called AskUserForTableNumber() or GetTableNumberFromInput(). Something like that. You are also both setting a member field and returning the value. So there are a bunch of ways you could store and retrieve that value. If the member field tablenumber was marked as public, you could access it. Or in your main function you could do this:
int tablenum=TO.TableNumber();
and then reuse that value.
Another odd thing you are doing is storing the input string as a member field. If you don't need to reference that string again, then there's no reason for that to be a member of the TableOrder object, it could be a local variable to the function that is doing the input.
But it seems like you are trying to use TableOrder.TableNumber like a property. And that very well may be the right thing to do, but not in the way that you are doing it. Here is a (sort of fancy) way of doing something similar, which also uses a concept of lazy-loading...
class TableOrder
{
private int? _tablenumber;
public int TableNumber
{
get
{
return _tablenumber ?? (_tablenumber=GetTableNumberFromInput());
}
set
{
_tablenumber = value;
}
}
private static int GetTableNumberFromInput()
{
Console.Write("please enter the table number:");
string inputtablenumber = Console.ReadLine();
return int.Parse(inputtablenumber);
}
//(and so on for other member properties)
}
This way, the first time you try to access table number, it will ask the user for the value. Afterward, you will already have the value, so it will not ask again. Note that this type of approach is not really necessary, and is mainly useful for waiting to load a value until you need to use that value. Instead you could just do something like: TableOrder.TableNumber = GetTableNumberFromInput();
First of all, you can remove the calls in your main since the method tableinfo() will call them:
class Program
{
static void Main(string[] args)
{
TableOrder TO = new TableOrder();
TO.tableinfo();
}
}
Second, you want to use the class variables that you already declared,
The returned value of the two functions are stored inside those and you can output them with Write.
public void tableinfo()
{
tablenumber = TableNumber();
Console.Write(tablenumber + 1);
numberAtTable = NumberOfPartons();
Console.WriteLine(numberAtTable + 1);
}
In the scope of this function, the return values (return numberAtTable and return tablenumber) don't exist anymore, they are stored in whats left of the called functions.

User Interaction with chain List Items

I have the following List items and try to find out an algorithm which takes care of user interaction.
tableItems.Add (new TableItem() {Start=1000, End=4000});
tableItems.Add (new TableItem() {Start=4000, End=6000});
tableItems.Add (new TableItem() {Start=6000, End=8000});
For example in the list, if user changes the first item "End" value that affects also second list item's "Start" value. That has to match. It is like a chain. Also, if user wants to change second item "Start" value, then the first item "End" value has to match as well.
What is effective way of solving this chain problem?
void Main()
{
var rangeManager = new RangeManager();
rangeManager.SetRange(3, 6000, 9000);
rangeManager.GetRange(3).Dump();
rangeManager.SetRange(1, 500, 4000);
rangeManager.GetRange(1).Dump();
}
public class RangeManager
{
private List<int> _values;
public RangeManager()
{
_values = new List<int> { 0, 1000, 4000, 6000, 8000 };
}
public Range GetRange(int index)
{
// TODO check for index out of range
return new Range(_values[index], _values[index + 1]);
}
public void SetRange(int index, int start, int finish)
{
// TODO check for index out of range
// TODO make sure start less than finish
// TODO make sure start greater than previous value
// TODO make sure finish less than next + 1 value
_values[index] = start;
_values[index + 1] = finish;
}
}
public class Range
{
public int Start { get; private set; }
public int Finish { get; private set; }
public Range(int start, int finish)
{
Start = start;
Finish = finish;
}
}
To understand what's going on here, start with the Range class. It is simply a holder for Start and Finish.
Next, look at the RangeManager class. It encapsulates the management of your chained ranges. It holds the values (range endpoints) in a list on integers (rather than a list of Range objects). This is a better way to store the data, because you no longer need to update neighboring objects when updating a range. Also, note that it's better to use integers than strings. The RangeManager class also has methods to help you manipulate and output your ranges.
Finally, look at the Main method. This shows an example of how to use the RangeManager and allows you to test whether it is working properly.

c# Using ArrayLists inside properties

I want to be able to have a class Named Musician, with a rule/Property called Hits( which is an Array-list, with two methods called ListHits() and AddHits(string)
ListHits returns a string containing all the hits separa
ted by a comma
AddHit – adds a hit to the Hits arrayList. Each hit is
a string between 1 and 50 characters long with no l
eading
or trailing white space.
I have no idea how to go about doing this im familiar with collections and adding values to Lists and i know how to set basic properties
-- i have tried for hours on end please HELP!
public class Musician : Celebrity
{
private string _hits;
public string Hits
{
get { return _hits; }
set
{
if (value.Length < 1)
{
throw new Exception("need more then 2 characters");
}
if (value.Length > 50)
{
throw new Exception("needs to be less then 50 characters");
}
else
{
_hits = value.Trim();
}
}
}
public Musician()
{
//
// TODO: Add constructor logic here
//
}
}
First off, you should try using a List<string> rather than an ArrayList. ArrayList was what you used before C# added generics in version 2.0. List<T> allows you to retain typing information about the items in the list, which enables you to more easily write correct code.
The code you posted didn't seem to really match the details you were asking for, but something like this should do what you specified:
public class Musician
{
private List<string> _hits;
public string ListHits()
{
return string.Join(", ", _hits);
}
public void AddHit(string hit)
{
/*
* validate the hit
*/
_hits.Add(hit);
}
}
The key is using string.Join to convert the _hits list into a comma-delimited string. From there, the rest is just basic C# concepts.

Categories

Resources