Good day all.
I am working on something that handles tasks.
Each task consists of 3 strings and a DateTime Object
Below is the constructor I built.
public Task(string von, string was, string an, DateTime zeit = DateTime.Now)
When compiling I get compiler error
Default parameter value for 'zeit' must be a compile-time constant (CS1736)
I assume the problem is, that -obvioulsy- the value for DateTime.Now depends on the time the constructor is called, which is the whole point that I want to have here.
I already looked at [this] thread, but it does not really apply to me, because the memory demand for a DateTime Object is always the same and that thread says the problem is the unknown heap-demand of that call.1
I already have an idea for a work-around (see below), but as we all know work-arounds are not best practice
public Task(string von, string was, string an, DateTime zeit){
if(zeit == null)
dateOfCreation = DateTime.Now; //dateOfCreation being the name of Task's internal DateTime field.
else
dateOfCretion = zeit;
So if I want to use the current DateTime I pass null. However: If I take the time and effort to always specifically pass null, I might as well each time pass DateTime.Now.
Question:
Is there a way to get parameter DateTime zeit = DateTime.Now accepted or substituted with identical outcome?
Use Constructor overloading instead:
public Task(string von, string was, string an, DateTime zeit)
{
...
}
public Task(string von, string was, string an) : this(von, was, an, DateTime.Now)
{
...
}
Related
I came across the accepted answer of this question about dealing with DateTime.Now in unit tests which contains the following code example:
private readonly Func<DateTime> _nowProvider;
public SomeClass(Func<DateTime> nowProvider)
{
_nowProvider = nowProvider;
}
public bool Foo()
{
return (_nowProvider().DayOfWeek == DayOfWeek.Sunday);
}
Instantiated as such:
var s = new SomeClass(() => DateTime.Now);
I've not much used Func<T> in C# so I thought I'd take a look at the Microsoft documentation for it which has the following remarks:
You can use this delegate to represent a method that can be passed as a parameter without explicitly declaring a custom delegate. The encapsulated method must correspond to the method signature that is defined by this delegate. This means that the encapsulated method must have no parameters and must return a value.
Why would it be more beneficial in the example to pass a Func<DateTime>, instantiated as Class(() => DateTime.Now) to the constructor
Rather than to just simply pass in a DateTime parameter instantiated as Class(DateTime.Now) to the constructor?
According to the Microsoft documentation mentioned above LINQ lambda constructors also take Func<T> arguments and my experience with these proves they are extremely flexible but I can't understand why?
Rather than to just simply pass in a DateTime parameter instantiated as Class(DateTime.Now) to the constructor?
Because the value should be the current DateTime and not the one when the class has been instanciated.
When the code runs, the Func returns the Date of exactly when the code is executed.
If the DateTime would be stored in a field, it would be the time of creation, not now.
I have an example.
Let's say you create an instance of Class at 23:59:55 on Saturday.
10 Seconds later, the following snipped:
(passedDateTime.DayOfWeek == DayOfWeek.Sunday);
would return false.
With the provider, the datetime is actually on sunday - the time it is executed at.
Technical:
DateTime is a struct.
When passing DateTime to a method or constructor as a parameter, it is passed as a value, not a reference.
Thus the DateTime will not be up to date, but just a snapshot of the value.
You can confirm this yourself:
var dateTime = DateTime.Now;
System.Threading.Sleep(1000);
bool equals = dateTime == DateTime.Now; // false
This pattern allows the Date and Time to be provided either by DateTime.Now, during normal operation, or to be closely controlled during unit testing.
For example, a Unit Test that wants to test time based functionality could verify that the returned result is correct when a function is called twice with more than 5 minutes between each call (a common caching technique), without having to wait 5 minutes between calls.
It is also an example of the "Inversion of Control" pattern. Where a method of retrieving data is "injected" in to the class, usually via constructor. The class is then free to use whatever method was injected without being aware of its implementation.
I attach a small example on how this could look like in a unit test.
If you would not have the ability to provide a different "Now" the unit test will behave different depending on the time it runs.
[TestMethod]
public void TestFoo()
{
var obj = new SomeClass(() => DateTime.Now);
//Only true on sundays
Assert.IsTrue(obj.Foo());
//This is sunday
obj = new SomeClass(() => new DateTime(2017, 7, 30));
//This will be always true
Assert.IsTrue(obj.Foo());
//This is not sunday
obj = new SomeClass(() => new DateTime(2017, 7, 29));
//This will be always false
Assert.IsFalse(obj.Foo());
}
We are trying to override the DateTime.MinValue in our application, but by doing it we noticed that our Web services are timing-out, following is a sample code. Not sure what is wrong/what we are missing.
public MainWindow()
{
//Introducing this.. Causes timeout of the webservice call...
typeof(DateTime).GetField("MinValue").SetValue(typeof(DateTime),new DateTime(1900, 1, 1));
var yesitworks= DateTime.MinValue;
InitializeComponent();
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
//Below call will timeout...
var value =client.GetData(10);
}
PS: This might not be the best solution for what we are trying resolve but now its more of curiosity as to why it is not working? how is it related.
DateTime.MinValue is a static readonly field. That means that library authors will not expect it to change, and may write code that depends on it having the expected value.
Hence, you should not change the value of DateTime.MinValue.
For example, a library may use it as the default value for a variable:
private mostRecentDate= DateTime.MinValue;
foreach (var date in myDates)
{
if (date > mostRecentDate)
{
mostRecentDate= date;
}
}
// Do something with the most recent date in myDates...
In this example, if myDates only contained dates earlier than your new value for DateTime.MinValue, then this code would set mostRecentDate to DateTime.MinValue rather than the latest date in myDates.
While this rather contrived example may not be good programming practise (for example, you could use Nullable instead), it is valid code, whose behaviour would be changed if you changed the value of DateTime.MinValue.
The point is that libraries you are using could also be dependant on the value on DateTime.MinValue, so changing it could break them. You are llucky in so far as you found out that this introduced a bug early. If you are unlucky, you would not see a problem until your software had gone live and some corner case was hit.
I had a similar problem recently.
You didn't tell why you wanted to override DateTime.MinValue, but I guess the reason is similar to mine:
I have a server written in .NET, which has .NET clients and (via COM-Interop) MS Access clients.
The clients pass DateTime values, and the server needs to check whether they passed a "real" value or DateTime.MinValue.
My problem was:
.NET's DateTime.MinValue is January 1st of the year 1
The smallest possible value for VBA's Date type is January 1st of the year 100
⇒ Checking for DateTime.MinValue didn't work when the data was coming from MS Access, because Date variables in Access can't hold a date as small as .NET's DateTime.MinValue.
At that point I tried to override DateTime.MinValue too, and found out it doesn't work.
My solution was to write an extension method for DateTime:
public static class DateTimeExtensions
{
public static bool MinValue(this DateTime input)
{
// check the min values of .NET *and* VBA
if (input == DateTime.MinValue || input == new DateTime(100, 1, 1))
{
return true;
}
return false;
}
}
For the code in your question, it would need to look like this:
public static class DateTimeExtensions
{
public static bool MinValue(this DateTime input)
{
if (input == new DateTime(1900, 1, 1))
{
return true;
}
return false;
}
}
Usage:
DateTime theDate = DateTime.Now;
// vanilla .NET
bool isMin1 = (theDate == DateTime.MinValue);
// with the extension method
bool isMin2 = theDate.MinValue();
I don't think you will be able to change the DateTime MinValue as it is read only, But if you can DON'T
DateTime:
public struct DateTime : IComparable, IFormattable, IConvertible, ISerializable, IComparable<DateTime>, IEquatable<DateTime>
{
public static readonly DateTime MaxValue
public static readonly DateTime MinValue
....
In the following method, parameters fromDate and toDate's value are never used because they are overwritten in the body before being read.
static void GetDatesFromMonth(string month, ref DateTime fromDate, ref DateTime toDate)
{
DateTime userDateTime = TimeHelper.getUserGMTNow();
DateTime calculatedDate = Convert.ToDateTime(month + " 01," + userDateTime.Year);
toDate = calculatedDate.AddMonths(1).AddSeconds(-1);
fromDate = toDate.AddMonths(-12).AddSeconds(1);
}
I am using this code at many places in my class file.
When I run Resharper on my code it shows this message and unlike all its other suggessions it is not able to correct this code block
can anybody help me to rewrite this method with good coding practice.
Change the two date parameters to out
static void GetDatesFromMonth(string month, out DateTime fromDate, out DateTime toDate)
See here for a clarification on out vs ref
Simply, you use out when your method need to return two or more values, the out means 'I will set this values before exiting'. On the contrary ref is more complicated. It means 'I need this values/objects inside this method and I will change them before exit'
Alternatively since out parameters are generally a code smell you may want to rewrite your method as something like:
static Tuple<DateTime, DateTime> GetDatesFromMonth(string month)
{
...
}
or
static ToFromDates GetDatesFromMonth(string month)
{
...
}
with
class ToFromDates
{
public DateTime To{get;set;}
public DateTime From{get;set;}
}
You could also create an extension method
static class DateExtensions
{
public static Tuple<DateTime, DateTime> GetDatesFromMonth(this string month)
{
...
}
}
and use this in your code like this
var dates = "January".GetDatesFromMonth();
Simply use out in place of ref. It will show your intentions (that parameters will be out parameters) and it will also indicate that initial values of those parameters are irrelevant. That should also fix R# warning. If you use ref, R# expects you to use the parameter values before any overwrite.
Normally, if I have a nullable type for an optional parameter, I would put null as the default value. This way I know that if the value is null, the caller doesn't want to specify any value for that one.
public void Foo(string text, string text2= null);
If the parameter is normally a positive integer, I can use a negative number
public void Foo(string text, int index=-1);
How about DateTime? It is not nullable, and (as far as I know) it doesn't have a meaningless number that cannot be a true input either (like -1 for positive integer). Or is there? What would you use in this situation?
I also know that I can use the nullable DateTime type, but this means that the method caller will have to use Nullable as well as opposed to just conveniently pass a DateTime.
You can make value types nullable using the ? operator in C#:
DateTime? myDate = null;
From this, you can make the parameter optional:
void Foo(DateTime? myDate = null)
{
}
Further reading on Nullable Types.
This is not the only way to skin the cat however, you can use default(DateTime), however you cannot use DateTime.MinValue, MaxValue, or Now in optional parameters because they are not compile time constants.
Of course, you don't need to use optional parameters, you can use overloaded methods if you wish to make use of Min, Max, or Now.
void Foo()
{
Foo(DateTime.MinValue);
}
void Foo(DateTime d)
{
}
If you want to go overkill (well, maybe not overkill, plenty of valid reasons to do this), then you could define a new date type that understands when it has a value:
class SmarterDateTime
{
public bool IsSet { get; set; }
// Wrapper around DateTime etc excluded.
}
As for what should be the default, you can choose to make any date represent a default if you wish, but for things like optional parameters you'll have limitations.
Personally, I tend to use DateTime.MinValue.
default (DateTime) - operator default is intended for It
At the question "what can be a default value for a DateTime" the response must be: you can only use default(DateTime). This because the default value must be const and both DateTime.MinValue and DateTime.MaxValue are only static readonly, but note that
default(DateTime) == DateTime.MinValue
down to the Kind.
If you want you can implement an overload with one less parameter (the DateTime) and from that overload call the "main" method passing the value you prefer.
But as written by others, the problem is that you wrote wrong premises.
No, DateTime (as nearly all the ValueTypes. Nearly all because Nullable<Nullable<int>> is illegal, even while Nullable<T> is a ValueType) is nullable. Nullable<DateTime> or DateTime? (same thing)
Even int are nullable, you know? int? :-)
DateTime.MinValue will be the default value.
check the dateTime default parameter , its value would be 1/1/0001 12:00:00 AM,
private void M(Int32 x = 9, String s = “A”, DateTimedt = default(DateTime), Guidguid = new Guid()) {
Console.WriteLine(“x={0}, s={1}, dt={2}, guid={3}”, x, s, dt, guid);
}
If you use the Nullable the callers of your function can just pass a regular DateTime to it, so they won't notice a thing :) There are implicit operators that will do this for you
If you want to set a default in your function you can do:
public void Foo(DateTime? value = null)
{
if ( value == null )
{
value = ... // default
}
}
Code Snippet
public DateTime method1()
{
if (condition)
return new DateTime(2007, 5, 30, 11, 32, 00);
else
return default(DateTime);
}
The default statement will initialise a value type to it's default value. In the case of a datetime this value is also exposed as a static property called DateTime.MinValue. If using C# 1.0 the statement "default(DateTime)" would be equivalent to "DateTime.MinValue". You could use this special value as a kind of "marker" value, meaning if it is returned it indicates an invalid datetime.
If using C# 2.0 again, it is also possible to use what is called a nullable type, and actually return NULL, as shown in the following example
Code Snippet
public DateTime? method2()
{
if (condition)
return new DateTime(2007, 5, 30, 11, 32, 00);
else
return null;
}
// This is the best way to null out the DateTime.
//
DateTime dateTime2 = DateTime.MinValue;
You might consider using the value DateTime.MinValue and use overloading.
Depends on your use-case.
Any that won't match real data will work, but that depends on your use of it (so in a way does -1 for integers, since it's a perfectly good integer only for your use of it being one were only positive integers make sense).
If you are sending a minimum date (interested in all foo that are later) then any date prior to the earliest sensible date will do, and code like .Where(f -> f.When > myDate) will work without even having to look for that special case.
Likewise with maximum dates in reverse (any date that would be after the latest sensible date).
Otherwise, just avoid the use of defaults entirely, and overload instead.
I want to write a 'Date' class that behaves like a Value Type.
for example, Instead of writing a Clone method for setting properties safely, make the Date class to pass by value:
public Date Birthday
{
get { return this.birthday; }
set
{
this.birthday = value.Clone();
} //I want to write this.birthday = value;
//without changing external value when this.Birthday changes
}
I know this is possible because System.String is a class and behaves like a value. for example:
String s1 = "Hello";
String s2 = "Hi";
s1 = s2;
s2="Hello";
Console.WriteLine(s1); //Prints 'Hi'
First I thought writers of this class override '=' operator, but now I know that the '=' operator can not be overridden. so how they write String class?
Edit: I just want to make my Date class to pass it's instances by value, like as String.
First, your string-based example does not illustrate your question.
The thing with DateTime and String is that they are immutable: once an instance is created, it cannot be changed in any way. For example, you cannot add 2 minutes to a DateTime instance by just saying date.Minutes += 2: you'll have to invoke date.AddMinutes(2), which will yield a totally new instance.
To make objects read-only, just follow the same pattern.
public class Date{ ...code...} would be a reference type...not what you want.
public struct Date { ...code...} would be a value type...probably what you want.
The string class is, as it is a class, a reference type...and is immutable..how being immutable effects the behavior of string objects can be confusing at the start.
Given string s1 = "Fish"; s1 is a reference that points to "Fish"...It is the "Fish" bit can never be changed....what s1 points to can be changed. If you then assign s1 = "Tuna"; "Fish" still exists but is no longer referenced and will be GC'd.
In your example after: s1=s2 s1,s2 now reference the same string "Hi"...there is only one "Hi".
I hope I have not gone way below your level.
It's not the '=' operator, it's the fact that when you say
stringThing = "thing";
you're creating a new string, not changing the current string to something else.