Why is my Stopwatch not adding time?
Why is my Stopwatch not adding time?
The class won't add on to the Stopwatch time using Speedrun.AddToTime(h, m, s)
No clue as to why!
class Speedrun
{
private static Stopwatch sr = new Stopwatch();
public static void Go()
{
sr.Reset();
sr.Start();
}
public static string GetTime
{
get
{
return sr.Elapsed.Hours + "h " + sr.Elapsed.Minutes + "m " + sr.Elapsed.Seconds + "s";
}
}
public static void AddToTime(int hours, int minutes, int seconds)
{
TimeSpan ts = new TimeSpan(hours, minutes, seconds);
sr.Elapsed.Add(ts);
}
public static void Stop()
{
sr.Stop();
}
public static void Cont()
{
sr.Start();
}
}
Fairly straight forward, I'm referencing it using the class name itself, instead of a variable. As seen here
Speedrun.Go();
Any help would be greatly appreciated!
UPDATE!!
CHEAP solution found here it is to help you guys that might have the similar situation
class Speedrun
{
private static Stopwatch sr = new Stopwatch();
private static int addedhours = 0;
private static int addedminutes = 0;
private static int addedseconds = 0;
public static void Go()
{
sr.Reset();
sr.Start();
addedhours = 0;
addedminutes = 0;
addedseconds = 0;
}
public static string GetTime
{
get
{
return (sr.Elapsed.Hours + addedhours) + "h " + (sr.Elapsed.Minutes + addedminutes) + "m " + (sr.Elapsed.Seconds + addedseconds) + "s";
}
}
public static void AddToTime(int hours, int minutes, int seconds)
{
addedhours = addedhours + hours;
addedminutes = addedminutes + minutes;
addedseconds = addedseconds + seconds;
}
public static void Stop()
{
sr.Stop();
}
public static void Cont()
{
sr.Start();
}
}
5 Answers
5
You're calling Add on a TimeSpan. TimeSpan is an immutable value type. You're doing nothing with the result here:
Add
TimeSpan
TimeSpan
sr.Elapsed.Add(ts);
... so it's effectively a no-op. Even if TimeSpan were immutable, it's still a value type - so you'd be fetching the property value (which would make a copy), then calling Add, and the mutated copy would then be lost.
TimeSpan
Add
Basically, what you're trying to do here won't work.
EDIT: Your workaround doesn't really work either, because if it's taken 35 seconds and you're adding 30 seconds, you'll end up reporting 65 seconds instead of 1 minutes and 5 seconds.
You should keep just a TimeSpan to add, then you can use something like:
TimeSpan
public static string GetTime
{
get
{
TimeSpan time = sr.Elapsed + timeToAdd;
// In .NET 4 you could use a custom format string for the TimeSpan
return string.Format("{0}h {1}m {2}s",
time.Hours, time.Minutes, time.Seconds);
}
}
I'm somewhat dubious of the overall design though - in particular, all these statics without any attempt at thread-safety makes me nervous... Do you really need all of this to be static to start with?
Even if TimeSpan were immutable
Ohhhh, I see. But still can't figure out a bloody solution. I did however come up with one that is cheap, which works the same way. I'll post it.
– JeremyC
May 1 '12 at 20:22
@user537156: Your solution is a bit broken. I'll edit to suggest an alternative...
– Jon Skeet
May 1 '12 at 20:34
TimeSpan.Add() doesn't modify the existing value, but returns a new resultant TimeSpan. So you'll need to change:
sr.Elapsed.Add(ts);
... so that it actually stores the result somewhere useful.
That stores the result in a temporary object which is then discarded.
– Mud
May 1 '12 at 20:17
@Mud: It doesn't have to. The author would need to handle that logic outside of the Stopwatch.
– Austin Salonen
May 1 '12 at 20:19
@MUd what are you talking about? I said the OP needs to store the result somewhere useful. I was quoting their current code, not the code to change to. Please read responses carefully, especially before handing out negative reputation.
– itsme86
May 1 '12 at 20:21
@itsme86 Gotcha. Can't retract my vote unless you edit your answer.
– Mud
May 1 '12 at 20:25
StopWatch.Elapsed returns a new TimeSpan object. Calling Add on that object creates yet another TimeSpan object, which you then discard.
StopWatch.Elapsed
TimeSpan
Add
TimeSpan
You're not writing anything back to your StopWatch object.
StopWatch
Try this:
class Speedrun
{
private static Stopwatch sr = new Stopwatch();
private static TimeSpan elapsed = new TimeSpan();
public static void Go()
{
elapsed = new TimeSpan(0);
sr.Reset();
sr.Start();
}
public static string GetTime
{
get
{
elapsed = elapsed.Add(sr.Elapsed);
return elapsed.Hours + "h " + elapsed.Minutes + "m " + elapsed.Seconds + "s";
}
}
public static void AddToTime(int hours, int minutes, int seconds)
{
TimeSpan ts = new TimeSpan(hours, minutes, seconds);
elapsed = elapsed.Add(ts);
}
public static void Stop()
{
sr.Stop();
}
public static void Cont()
{
sr.Start();
}
}
FYI, GetTime is an appropriate name for a method. A better name for a property would simply be Time or ElapsedTime.
GetTime
Time
ElapsedTime
All he really needs to do is give his class a
TimeSpan member, put the result of sr.Elapsed.Add(ts); into that, and then reference it instead of the StopWatch in the GetTime method...– Dan J
May 1 '12 at 20:22
TimeSpan
sr.Elapsed.Add(ts);
GetTime
See http://msdn.microsoft.com/en-us/library/system.timespan.add.aspx
Add returns a new TimeSpan object rather than mutating the existing, and since StopWatch.Elapsed is readonly I don't know if you can accomplish what you're trying
This is my solution...
public class StopwatchPlus : Stopwatch
{
private TimeSpan AddedTime { get; set; }
public StopwatchPlus() { AddedTime = new TimeSpan(0); }
public TimeSpan Elapsed { get { return base.Elapsed.Add(AddedTime); } }
public void Add(TimeSpan time) { AddedTime = AddedTime.Add(time); }
}
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Even if TimeSpan were immutableer, you mean mutable?– vcsjones
May 1 '12 at 20:16