If I have some foreach loops e.g.
foreach (ObjectA a in getAs(param1))
{
foreach (ObjectB b in getBs(param2))
{
//compare a & b
}
}
Assuming I don't make any edits to the returning lists (they are the same list returned), will the compiler be smart enough to only call getAs() & getBs() once, each? Will it even be smart enough to know that it should convert them to a dictionary?
Will the fact that it is eventually interacting with a SQL database, through LNQ, make a difference (e.g. perhaps the code assumes that a SQL database can change at any moment, but maybe it can do a check to see if it's changed?)
The short answer is No, but the long answer has more to do with the way your code is written rather than the efficiency of the compiler.
In your first foreach loop, you obtain the source once, and iterate through its elements, effectively calling the method only once in order to obtain the source, but the nested foreach loop is called once for every iteration in the outer loop, and since the compiler has no way of knowing if the output of the method in the nested loop won't change, it actually makes sense for it to always call the method in order to obtain the source to iterate through.
In this case you need to improve your logic and avoid unnecessary calls to methods if you know the output will be the same, specially if you know that there is some resource consuming operation (such as a call to a DB) going on inside that method.
For the sake of giving a detailed answer, i tried your statements in the following program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace StackOverflow
{
public class Class1
{
public static void Main(string[] args)
{
var serv1 = new Testserv1();
foreach (int x in serv1.CallA())
{
foreach (int y in serv1.CallB())
{
}
}
Console.WriteLine(string.Format("Calls to A: {0}", serv1.ACount));
Console.WriteLine(string.Format("Calls to B: {0}", serv1.BCount));
Console.ReadLine();
}
}
public class Testserv1
{
private static int CallACount = 0;
private static int CallBCount = 0;
public int ACount {
get
{
return CallACount;
}
}
public int BCount
{
get
{
return CallBCount;
}
}
public Testserv1()
{
//InitializeComponent();
}
public List<int> CallA()
{
CallACount++;
return new List<int>() {
1,2,3,4,5,6
};
}
public List<int> CallB()
{
CallBCount++;
return new List<int>() {
7,8,9,10,11,12
};
}
}
}
The output for the previous code is:
Calls to A: 1
Calls to B: 6
Given the information presented in your question, there is no legitimate reason to assume that the compiler would convert to a dictionary. In fact, there is no reason for a dictionary. Why would one expect the compiler to divine a unique key from a method call result?
The question posed does not provide sufficient information to even reply with a relevant response.
Necessary details include:
What are the return types of the methods getAs and getBs?
On what basis are the comparisons being made?
What is the usage and result type expected from the loop?
Each loop is using a different object, on what basis would one assume the compile would optimize in any manner given the complete lack of forthright information?
Given a more specific example such as this:
List<string> intersection = new List<string>();
foreach (string a in GetaList())
{
foreach (string b in GetbList())
{
if (a.Equals(b))
{
intersection.Add(a);
}
}
}
The assembly (F11 to step in, CTRL-F11 to view assembly) would indicate that the GetbList is actually getting called for each iteration, at least in debug mode.
I believe the answer to your question is: No, the compiler is not optimizing the inner method call for you. If you want the inner method call to occur only once, make the call outside the outer loop.
Related
I have this example code. What I want to do is to make it so that the "Nums" value can only be written to using the "AddNum" method.
namespace ConsoleApplication1
{
public class Person
{
string myName = "N/A";
int myAge = 0;
List<int> _nums = new List<int>();
public List<int> Nums
{
get
{
return _nums;
}
}
public void AddNum(int NumToAdd)
{
_nums.Add(NumToAdd);
}
public string Name { get; set; }
public int Age { get; set; }
}
}
Somehow, I've tried a bunch of things regarding AsReadOnly() and the readonly keyword, but I can't seem to get it to do what I want it to do.
Here is the sample of the code I have to access the property.
Person p1 = new Person();
p1.Nums.Add(25); //access 1
p1.AddNum(37); //access 2
Console.WriteLine("press any key");
Console.ReadLine();
I really want "access 1" to fail, and "access 2" to be the ONLY way that the value can be set. Thanks in advance for the help.
√ DO use ReadOnlyCollection, a subclass of ReadOnlyCollection,
or in rare cases IEnumerable for properties or return values
representing read-only collections.
The quote from this article.
You should have something like this:
List<int> _nums = new List<int>();
public ReadOnlyCollection<int> Nums
{
get
{
return _nums.AsReadOnly();
}
}
In general, collection types make poor properties because even when a collection is wrapped in ReadOnlyCollection, it's inherently unclear what:
IEnumerable<int> nums = myPerson.Nums;
myPerson.AddNum(23);
foreach(int i in nums) // Should the 23 be included!?
...
is supposed to mean. Is the object returned from Nums a snapshot of the numbers that existed when it called, is it a live view?
A cleaner approach is to have a method called something like GetNumsAsArray which returns a new array each time it's called; it may also be helpful in some cases to have a GetNumsAsList variant depending upon what the caller will want to do with the numbers. Some methods only work with arrays, and some only work with lists, so if only one of the above is provided some callers will have to call it and then convert the returned object to the required type.
If performance-sensitive callers will be needing to use this code a lot, it may be helpful to have a more general-purpose method:
int CopyNumsIntoArray(int sourceIndex, int reqCount, ref int[] dest,
int destIndex, CopyCountMode mode);
where CopyCountMode indicates what the code should do the number of items available starting at sourceIndex is greater or less than reqCount; the method should either return the number of items that were available, or throw an exception if it violated the caller's stated expectations. Some callers might start by create and passing in a 10-item array but be prepared to have the method replace it with a bigger array if there are more than ten items to be returned; others might expect that there will be exactly 23 items and be unprepared to handle any other number. Using a parameter to specify the mode will allow one method to service many kinds of callers.
Although many collection authors don't bother including any method that fits the above pattern, such methods can greatly improve efficiency in cases where code wants to work with a significant minority of a collection (e.g. 1,000 items out of a collection of 50,000). In the absence of such methods, code wishing to work with such a range must either ask for a copy of the whole thing (very wasteful) or request thousands of items individually (also wasteful). Allowing the caller to supply the destination array would improve efficiency in the case where the same method makes many queries, especially if the destination array would be large enough to be put on the large object heap.
Lets assume you have a function that returns a lazily-enumerated object:
struct AnimalCount
{
int Chickens;
int Goats;
}
IEnumerable<AnimalCount> FarmsInEachPen()
{
....
yield new AnimalCount(x, y);
....
}
You also have two functions that consume two separate IEnumerables, for example:
ConsumeChicken(IEnumerable<int>);
ConsumeGoat(IEnumerable<int>);
How can you call ConsumeChicken and ConsumeGoat without a) converting FarmsInEachPen() ToList() beforehand because it might have two zillion records, b) no multi-threading.
Basically:
ConsumeChicken(FarmsInEachPen().Select(x => x.Chickens));
ConsumeGoats(FarmsInEachPen().Select(x => x.Goats));
But without forcing the double enumeration.
I can solve it with multithread, but it gets unnecessarily complicated with a buffer queue for each list.
So I'm looking for a way to split the AnimalCount enumerator into two int enumerators without fully evaluating AnimalCount. There is no problem running ConsumeGoat and ConsumeChicken together in lock-step.
I can feel the solution just out of my grasp but I'm not quite there. I'm thinking along the lines of a helper function that returns an IEnumerable being fed into ConsumeChicken and each time the iterator is used, it internally calls ConsumeGoat, thus executing the two functions in lock-step. Except, of course, I don't want to call ConsumeGoat more than once..
I don't think there is a way to do what you want, since ConsumeChickens(IEnumerable<int>) and ConsumeGoats(IEnumerable<int>) are being called sequentially, each of them enumerating a list separately - how do you expect that to work without two separate enumerations of the list?
Depending on the situation, a better solution is to have ConsumeChicken(int) and ConsumeGoat(int) methods (which each consume a single item), and call them in alternation. Like this:
foreach(var animal in animals)
{
ConsomeChicken(animal.Chickens);
ConsomeGoat(animal.Goats);
}
This will enumerate the animals collection only once.
Also, a note: depending on your LINQ-provider and what exactly it is you're trying to do, there may be better options. For example, if you're trying to get the total sum of both chickens and goats from a database using linq-to-sql or linq-to-entities, the following query..
from a in animals
group a by 0 into g
select new
{
TotalChickens = g.Sum(x => x.Chickens),
TotalGoats = g.Sum(x => x.Goats)
}
will result in a single query, and do the summation on the database-end, which is greatly preferable to pulling the entire table over and doing the summation on the client end.
The way you have posed your problem, there is no way to do this. IEnumerable<T> is a pull enumerable - that is, you can GetEnumerator to the front of the sequence and then repeatedly ask "Give me the next item" (MoveNext/Current). You can't, on one thread, have two different things pulling from the animals.Select(a => a.Chickens) and animals.Select(a => a.Goats) at the same time. You would have to do one then the other (which would require materializing the second).
The suggestion BlueRaja made is one way to change the problem slightly. I would suggest going that route.
The other alternative is to utilize IObservable<T> from Microsoft's reactive extensions (Rx), a push enumerable. I won't go into the details of how you would do that, but it's something you could look into.
Edit:
The above is assuming that ConsumeChickens and ConsumeGoats are both returning void or are at least not returning IEnumerable<T> themselves - which seems like an obvious assumption. I'd appreciate it if the lame downvoter would actually comment.
Actually simples way to achieve what you what is convert FarmsInEachPen return value to push collection or IObservable and use ReactiveExtensions for working with it
var observable = new Subject<Animals>()
observable.Do(x=> DoSomethingWithChicken(x. Chickens))
observable.Do(x=> DoSomethingWithGoat(x.Goats))
foreach(var item in FarmsInEachPen())
{
observable.OnNext(item)
}
I figured it out, thanks in large part due to the path that #Lee put me on.
You need to share a single enumerator between the two zips, and use an adapter function to project the correct element into the sequence.
private static IEnumerable<object> ConsumeChickens(IEnumerable<int> xList)
{
foreach (var x in xList)
{
Console.WriteLine("X: " + x);
yield return null;
}
}
private static IEnumerable<object> ConsumeGoats(IEnumerable<int> yList)
{
foreach (var y in yList)
{
Console.WriteLine("Y: " + y);
yield return null;
}
}
private static IEnumerable<int> SelectHelper(IEnumerator<AnimalCount> enumerator, int i)
{
bool c = i != 0 || enumerator.MoveNext();
while (c)
{
if (i == 0)
{
yield return enumerator.Current.Chickens;
c = enumerator.MoveNext();
}
else
{
yield return enumerator.Current.Goats;
}
}
}
private static void Main(string[] args)
{
var enumerator = GetAnimals().GetEnumerator();
var chickensList = ConsumeChickens(SelectHelper(enumerator, 0));
var goatsList = ConsumeGoats(SelectHelper(enumerator, 1));
var temp = chickensList.Zip(goatsList, (i, i1) => (object) null);
temp.ToList();
Console.WriteLine("Total iterations: " + iterations);
}
There are a number of different way to accomplish the same simple loop though the items of an object in c#.
This has made me wonder if there is any reason be it performance or ease of use, as to use on over the other. Or is it just down to personal preference.
Take a simple object
var myList = List<MyObject>;
Lets assume the object is filled and we want to iterate over the items.
Method 1.
foreach(var item in myList)
{
//Do stuff
}
Method 2
myList.Foreach(ml =>
{
//Do stuff
});
Method 3
while (myList.MoveNext())
{
//Do stuff
}
Method 4
for (int i = 0; i < myList.Count; i++)
{
//Do stuff
}
What I was wondering is do each of these compiled down to the same thing? is there a clear performance advantage for using one over the others?
or is this just down to personal preference when coding?
Have I missed any?
The answer the majority of the time is it does not matter. The number of items in the loop (even what one might consider a "large" number of items, say in the thousands) isn't going to have an impact on the code.
Of course, if you identify this as a bottleneck in your situation, by all means, address it, but you have to identify the bottleneck first.
That said, there are a number of things to take into consideration with each approach, which I'll outline here.
Let's define a few things first:
All of the tests were run on .NET 4.0 on a 32-bit processor.
TimeSpan.TicksPerSecond on my machine = 10,000,000
All tests were performed in separate unit test sessions, not in the same one (so as not to possibly interfere with garbage collections, etc.)
Here's some helpers that are needed for each test:
The MyObject class:
public class MyObject
{
public int IntValue { get; set; }
public double DoubleValue { get; set; }
}
A method to create a List<T> of any length of MyClass instances:
public static List<MyObject> CreateList(int items)
{
// Validate parmaeters.
if (items < 0)
throw new ArgumentOutOfRangeException("items", items,
"The items parameter must be a non-negative value.");
// Return the items in a list.
return Enumerable.Range(0, items).
Select(i => new MyObject { IntValue = i, DoubleValue = i }).
ToList();
}
An action to perform for each item in the list (needed because Method 2 uses a delegate, and a call needs to be made to something to measure impact):
public static void MyObjectAction(MyObject obj, TextWriter writer)
{
// Validate parameters.
Debug.Assert(obj != null);
Debug.Assert(writer != null);
// Write.
writer.WriteLine("MyObject.IntValue: {0}, MyObject.DoubleValue: {1}",
obj.IntValue, obj.DoubleValue);
}
A method to create a TextWriter which writes to a null Stream (basically a data sink):
public static TextWriter CreateNullTextWriter()
{
// Create a stream writer off a null stream.
return new StreamWriter(Stream.Null);
}
And let's fix the number of items at one million (1,000,000, which should be sufficiently high to enforce that generally, these all have about the same performance impact):
// The number of items to test.
public const int ItemsToTest = 1000000;
Let's get into the methods:
Method 1: foreach
The following code:
foreach(var item in myList)
{
//Do stuff
}
Compiles down into the following:
using (var enumerable = myList.GetEnumerable())
while (enumerable.MoveNext())
{
var item = enumerable.Current;
// Do stuff.
}
There's quite a bit going on there. You have the method calls (and it may or may not be against the IEnumerator<T> or IEnumerator interfaces, as the compiler respects duck-typing in this case) and your // Do stuff is hoisted into that while structure.
Here's the test to measure the performance:
[TestMethod]
public void TestForEachKeyword()
{
// Create the list.
List<MyObject> list = CreateList(ItemsToTest);
// Create the writer.
using (TextWriter writer = CreateNullTextWriter())
{
// Create the stopwatch.
Stopwatch s = Stopwatch.StartNew();
// Cycle through the items.
foreach (var item in list)
{
// Write the values.
MyObjectAction(item, writer);
}
// Write out the number of ticks.
Debug.WriteLine("Foreach loop ticks: {0}", s.ElapsedTicks);
}
}
The output:
Foreach loop ticks: 3210872841
Method 2: .ForEach method on List<T>
The code for the .ForEach method on List<T> looks something like this:
public void ForEach(Action<T> action)
{
// Error handling omitted
// Cycle through the items, perform action.
for (int index = 0; index < Count; ++index)
{
// Perform action.
action(this[index]);
}
}
Note that this is functionally equivalent to Method 4, with one exception, the code that is hoisted into the for loop is passed as a delegate. This requires a dereference to get to the code that needs to be executed. While the performance of delegates has improved from .NET 3.0 on, that overhead is there.
However, it's negligible. The test to measure the performance:
[TestMethod]
public void TestForEachMethod()
{
// Create the list.
List<MyObject> list = CreateList(ItemsToTest);
// Create the writer.
using (TextWriter writer = CreateNullTextWriter())
{
// Create the stopwatch.
Stopwatch s = Stopwatch.StartNew();
// Cycle through the items.
list.ForEach(i => MyObjectAction(i, writer));
// Write out the number of ticks.
Debug.WriteLine("ForEach method ticks: {0}", s.ElapsedTicks);
}
}
The output:
ForEach method ticks: 3135132204
That's actually ~7.5 seconds faster than using the foreach loop. Not completely surprising, given that it uses direct array access instead of using IEnumerable<T>.
Remember though, this translates to 0.0000075740637 seconds per item being saved. That's not worth it for small lists of items.
Method 3: while (myList.MoveNext())
As shown in Method 1, this is exactly what the compiler does (with the addition of the using statement, which is good practice). You're not gaining anything here by unwinding the code yourself that the compiler would otherwise generate.
For kicks, let's do it anyways:
[TestMethod]
public void TestEnumerator()
{
// Create the list.
List<MyObject> list = CreateList(ItemsToTest);
// Create the writer.
using (TextWriter writer = CreateNullTextWriter())
// Get the enumerator.
using (IEnumerator<MyObject> enumerator = list.GetEnumerator())
{
// Create the stopwatch.
Stopwatch s = Stopwatch.StartNew();
// Cycle through the items.
while (enumerator.MoveNext())
{
// Write.
MyObjectAction(enumerator.Current, writer);
}
// Write out the number of ticks.
Debug.WriteLine("Enumerator loop ticks: {0}", s.ElapsedTicks);
}
}
The output:
Enumerator loop ticks: 3241289895
Method 4: for
In this particular case, you're going to gain some speed, as the list indexer is going directly to the underlying array to perform the lookup (that's an implementation detail, BTW, there's nothing to say that it can't be a tree structure backing the List<T> up).
[TestMethod]
public void TestListIndexer()
{
// Create the list.
List<MyObject> list = CreateList(ItemsToTest);
// Create the writer.
using (TextWriter writer = CreateNullTextWriter())
{
// Create the stopwatch.
Stopwatch s = Stopwatch.StartNew();
// Cycle by index.
for (int i = 0; i < list.Count; ++i)
{
// Get the item.
MyObject item = list[i];
// Perform the action.
MyObjectAction(item, writer);
}
// Write out the number of ticks.
Debug.WriteLine("List indexer loop ticks: {0}", s.ElapsedTicks);
}
}
The output:
List indexer loop ticks: 3039649305
However the place where this can make a difference is arrays. Arrays can be unwound by the compiler to process multiple items at a time.
Instead of doing ten iterations of one item in a ten item loop, the compiler can unwind this into five iterations of two items in a ten item loop.
However, I'm not positive here that this is actually happening (I have to look at the IL and the output of the compiled IL).
Here's the test:
[TestMethod]
public void TestArray()
{
// Create the list.
MyObject[] array = CreateList(ItemsToTest).ToArray();
// Create the writer.
using (TextWriter writer = CreateNullTextWriter())
{
// Create the stopwatch.
Stopwatch s = Stopwatch.StartNew();
// Cycle by index.
for (int i = 0; i < array.Length; ++i)
{
// Get the item.
MyObject item = array[i];
// Perform the action.
MyObjectAction(item, writer);
}
// Write out the number of ticks.
Debug.WriteLine("Enumerator loop ticks: {0}", s.ElapsedTicks);
}
}
The output:
Array loop ticks: 3102911316
It should be noted that out-of-the box, Resharper offers a suggestion with a refactoring to change the above for statements to foreach statements. That's not to say this is right, but the basis is to reduce the amount of technical debt in code.
TL;DR
You really shouldn't be concerned with the performance of these things, unless testing in your situation shows that you have a real bottleneck (and you'll have to have massive numbers of items to have an impact).
Generally, you should go for what's most maintainable, in which case, Method 1 (foreach) is the way to go.
In regards to the final bit of the question, "Did I miss any?" Yes, and I feel I would be remiss to not mention this even though the question is quite old. While those four ways of doing it will execute in relatively the same amount of time, there is a way not shown above that runs faster than all of them. Quite significantly, in fact, as the number of items in the iterated list increases. It would be the exact same way as the last method but instead of getting .Count in the condition check of the loop, you assign this value to a variable before setting up the loop and use that instead. Which leaves you with something like this:
var countVar = list.Count;
for(int i = 0; i < countVar; i++)
{
//loop logic
}
By doing it this way, you're only looking up a variable value at each iteration, rather than resolving the Count or Length properties, which is considerably less efficient.
I would suggest an even better and not well-known approach for faster loop iteration over a list. I would recommend you to first read about Span<T>. Note that you can use it if you are using .NET Core.
List<MyObject> list = new();
foreach (MyObject item in CollectionsMarshal.AsSpan(list))
{
// Do something
}
Be aware of the caveats:
The CollectionsMarshal.AsSpan method is unsafe and should be used only if you know what you're doing. CollectionsMarshal.AsSpan returns a Span<T> on the private array of List<T>. Iterating over a Span<T> is fast as the JIT uses the same tricks as for optimizing arrays. Using this method, it won't check the list is not modified during the enumeration.
This is a more detailed explanation of what it does behind the scenes and more, super interesting!
Suppose I have the following code:
List<SomeObject> someObjects = ReturnListWithThousandsOfObjects();
foreach(SomeObject someobject in someObjects)
{
DoSomething.With(someObject);
}
And also suppose that after a minute of running I put a breakpoint on DoSomething.With(someObject);.
The debugger breaks for me just fine. But now I want to know what point am I at in my iteration of the list (assume the list is unordered/has no key).
Is there a way for the debugger to say "the foreach has run 532 of 2321 iterations"?
As a debugging one off isn't there an indexof method?
i.e.
quickwatch - someObjects.indexOf(someObject);
Added - Sorry if a bit brief.
As pointed out by Guffa this will work best if the values are unique or the default equality comparer EqualityComparer function uses a unique value (such as a custom GetHashCode/Equals overload).
public class ATest
{
public int number { get; set; }
public int boo { get; set; }
public ATest()
{
}
}
protected void Go()
{
List<ATest> list = new List<ATest>();
foreach(var i in Enumerable.Range(0,30)) {
foreach(var j in Enumerable.Range(0,100)) {
list.Add(new ATest() { number = i, boo = j });
}
}
var o =0; //only for proving concept.
foreach (ATest aTest in list)
{
DoSomthing(aTest);
//proof that this does work in this example.
o++;
System.Diagnostics.Debug.Assert(o == list.IndexOf(aTest));
}
}
This is for Visual Studio, but other IDEs should have something similar:
When you set a breakpoint you can right-click it and go to "Hit Count". You can setup some parameters there ("greater than or equal to " 0 will make it work like a regular breakpoint - so would "break always"). The interesting part is the Hit Count field (which can be reset).
This can solve the "number of iterations" part. For the total number I'm afraid you're going to have to find it yourself, assuming the collection you use has such a number readily available.
You can also set the breakpoint to fire after a very large number of hits, say a few thousands/millions (I don't know what is their limit).
Then, when the "real" breakpoint fires, the one where you want to know how many times the original breakpoint was hit, you can just examine it and reset it if needed.
Is this case, if you really wanted to know what the count is, wouldn't you use a for loop?
List<SomeObject> someObjects = ReturnListWithThousandsOfObjects();
for(int someObj= 1; someObj <= someObjects.Count; someObj++)
{
Console.WriteLine(string.Format("{0} of {1} iterations", someObj, someObjects.Count));
DoSomething.With(someObject[someObj]);
}
There will be no real difference in performance between the foreach and the for loops - therefore the for loop will be a better alternative for the situation you want to achieve.
Unless you manually keep count in a variable you won't be able to easily determine this. As the loop is iterating across your collection it just uses the enumerator to grab the next element in the collection tell there are no more elements at which point it exits.
To manually keep a count you would just do:
int count = 0;
List<SomeObject> someObjects = ReturnListWithThousandsOfObjects();
foreach(SomeObject someobject in someObjects)
{
count++;
DoSomething.With(someObject);
}
Now at any point you can pause execution and see which iteration you are on
Create an extension method on List and List which accepts a Action fold, Action sideFold that let's you accumulate side effects like checking for the existence of a debugger and breaking on accumulated state.
Yes it can. Here's how [in VS 2017] :
Set a break point inside the foreach loop
Right click the break point and select 'Actions'
In the text box, enter the following: $FUNCTION {list.Items.IndexOf(item)} where 'list' is the name of your list and 'item' is the current item
Continue running the code and watch the output window
I have the following assignment for homework.
Requirements
Design a class called TokenGiver with the following elements:
a default constructor, a parametrized constructor that takes an int
a method that adds a specified number of tokens to the number of tokens
a method that subtracts exactly ONE token from your number of tokens
a method that returns the number of tokens in your object
Other Requirements:
create a TokenGiver object
store 10 tokens in it
ask the TokenGiver object how many tokens it has and display the result
take 2 tokens out of the TokenGiver object
ask the TokenGiver object how many tokens it has and display the result
Question
Is there a better way to subtract two tokens at once from my Main() method, or is calling the GetToken() method twice the only way?
Code Snippet:
using System;
class Program
{
const int NUM_TOKENS = 10;
static void Main()
{
TokenGiver tokenMachine = new TokenGiver(NUM_TOKENS);
Console.WriteLine("Current number of tokens = {0}",
tokenMachine.CountTokens());
tokenMachine.GetToken();
tokenMachine.GetToken();
Console.WriteLine("New number of tokens = {0}",
tokenMachine.CountTokens());
Console.ReadLine();
}
}
class TokenGiver
{
private int numTokens;
public TokenGiver()
{
numTokens = 0;
}
public TokenGiver(int t)
{
numTokens = t;
}
public void AddTokens(int t)
{
numTokens += t;
}
public void GetToken()
{
numTokens--;
}
public int CountTokens()
{
return numTokens;
}
}
There is a better way, as Ed said. But with your assignment saying that you need a method to subtract exactly 1 Token, you are doing it how you should.
public void GetToken(int t)
{
numTokens -= t;
}
then you would could call GetToken(2);
Well, whether or not there is a better way to extract two tokens than by calling GetToken twice seems irrelevant because one of your requirements is:
(the class shall have) a method that subtracts exactly ONE token from your number of tokens
So, it seems you are stuck with two calls. Since this is a highly contrived assignment you may as well just stick to the requirements. If you really want to learn something start your own personal project. :)
Also, as an aside, you can chain constructors in C#. So this:
public TokenGiver()
{
numTokens = 0;
}
public TokenGiver(int t)
{
numTokens = t;
}
...becomes...
public TokenGiver() : this(0) { }
public TokenGiver(int t)
{
numTokens = t;
}
Given the requirements, you have to call GetToken twice... But of course it would be possible to create an overload for this method that would take the number of tokens to subtract as a parameter.
As a side note : GetToken is a poorly choosed name... usually a method whose name starts with "Get" is expected to return something. You could call it "TakeToken" instead, or something similar
His requirements say to create and THEN add the 10 tokens. You call the constructor with a 10 -- call the constructor with void and then add the ten. I believe this was the assignment.
To simply answer your question, what's wrong with tokenMachine.AddTokens(-2)? Given the requirements, it doesn't seem to be out of the question. The .NET framework also commonly uses this construction as well (e.g. DateTime.AddDays() takes a negative number to subtract).
However, a bad instructor may mark you off for this, using the argument that "[he intended to specify that] the machine can only dispense one token at a time", so it may be best to clarify the specifications.