Reputation: 42997
I have the following problem.
In a class I declare:
vulnerabilityDetailsTable.AddCell(new PdfPCell(new Phrase(currentVuln.Published.ToString(), _fontNormale)) { Border = PdfPCell.NO_BORDER, Padding = 5, MinimumHeight = 30, PaddingTop = 10 });
and the interesting part is: currentVuln.Published.ToString(). This work fine.
Published is a DateTime property declared as nullable, in this way:
public System.DateTime? Published { get; set; }
The problem is that in the previous way the printed value of currentVuln.Published.ToString() is something like 18/07/2014 00:00:00 (also the time is included in the date).
I want show only the date and not show the time so I tryed to use something like it:
currentVuln.Published.ToShortDateString()
But it don't work and I obtain the following error message in Visual Studio:
Error 4 'System.Nullable<System.DateTime>' does not contain a definition for 'ToShortDateString' and no extension method 'ToShortDateString' accepting a first argument of type 'System.Nullable<System.DateTime>' could be found (are you missing a using directive or an assembly reference?) C:\Develop\EarlyWarning\public\Implementazione\Ver2\PdfReport\PdfVulnerability.cs 93 101 PdfReport
It seems that this happen because my DateTime field is nullable.
What am i missing? How can I fix this issue?
Upvotes: 4
Views: 11452
Reputation: 66469
You're right, it's because your DateTime
field is nullable.
The extension methods for a DateTime
are unavailable for DateTime?
, but to understand why, you have to realize that there actually is no DateTime?
class.
Most commonly, we write nullable types using the ?
syntax, like DateTime?
, int?
, etc as you did above. But that's just syntactic sugar for Nullable<DateTime>
, Nullable<int>
, etc.
public Nullable<DateTime> Published { get; set; }
And all those apparently separate Nullable
types come from a single generic Nullable<T>
struct that wraps your type and provides two helpful properties:
HasValue
(for testing whether the underlying wrapped type has a value), andValue
(for accessing that underlying value, assuming there is one)Check to make sure there's a value first, then use the Value
property to access the underlying type (in this case, a DateTime
), along with any methods that are normally available for that type.
if (currentVuln.Published.HasValue)
{
// not sure what you're doing with it, so I'll just assign it...
var shortDate = currentVuln.Published.Value.ToShortDateString();
}
For C# 6.0 and higher you can use null conditional instead of .Value
:
var shortDate = currentVuln.Published?.ToShortDateString();
Upvotes: 16
Reputation: 41
Just in case someone else comes across this thread. You can use .value.ToShortDateString(). This will solve this issue.
Upvotes: 4
Reputation: 61982
The value type Nullable<>
encapsulates a value of another value type together with a boolean hasValue
.
This type Nullable<>
inherits the method string ToString()
from its ultimate base class, System.Object
. It also overrides this method with a new implementation. The new implementation returns ""
if hasValue
is false
, and returns the string it gets from .ToString()
on the encapsulated value (which also inherits System.Object
) if hasValue
is true
.
That is why your existing code is legal.
The type Nullable<>
does not have any method ToShortDateString
, though. You would have to go to the encapsulated value, through the Value
property. Therefore, instead of the illegal:
currentVuln.Published.ToShortDateString() /* error */
you will need
currentVuln.Published.HasValue ? currentVuln.Published.Value.ToShortDateString() : ""
or, equivalently
currentVuln.Published != null ? currentVuln.Published.Value.ToShortDateString() : ""
(both do the same at runtime). You could change the string ""
to something else, like "never"
or "not published"
if you wanted.
If it could be a problem that the Published
property (its get
accessor) is called twice, you would need to take out a temporary variable somewhere, var published = currentVuln.Published;
, and use that: published.HasValue ? published.Value.ToShortDateString() : ""
Upvotes: 2