Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# 4.0: Can I use a TimeSpan as an optional parameter with a default value?

People also ask

C dalam Latin berapa?

C adalah huruf ketiga dalam alfabet Latin. Dalam bahasa Indonesia, huruf ini disebut ce (dibaca [tʃe]).

Bahasa C digunakan untuk apa?

Meskipun C dibuat untuk memprogram sistem dan jaringan komputer namun bahasa ini juga sering digunakan dalam mengembangkan software aplikasi. C juga banyak dipakai oleh berbagai jenis platform sistem operasi dan arsitektur komputer, bahkan terdapat beberepa compiler yang sangat populer telah tersedia.

Bahasa C dibuat pertama kali oleh siapa dan tahun berapa?

Bahasa pemrograman C ini dikembangkan antara tahun 1969 – 1972 oleh Dennis Ritchie. Yang kemudian dipakai untuk menulis ulang sistem operasi UNIX. Selain untuk mengembangkan UNIX, bahasa C juga dirilis sebagai bahasa pemrograman umum.


You can work around this very easily by changing your signature.

void Foo(TimeSpan? span = null) {

   if (span == null) { span = TimeSpan.FromSeconds(2); }

   ...

}

I should elaborate - the reason those expressions in your example are not compile-time constants is because at compile time, the compiler can't simply execute TimeSpan.FromSeconds(2.0) and stick the bytes of the result into your compiled code.

As an example, consider if you tried to use DateTime.Now instead. The value of DateTime.Now changes every time it's executed. Or suppose that TimeSpan.FromSeconds took into account gravity. It's an absurd example but the rules of compile-time constants don't make special cases just because we happen to know that TimeSpan.FromSeconds is deterministic.


My VB6 heritage makes me uneasy with the idea of considering "null value" and "missing value" to be equivalent. In most cases, it's probably fine, but you might have an unintended side effect, or you might swallow an exceptional condition (for example, if the source of span is a property or variable that should not be null, but is).

I would therefore overload the method:

void Foo()
{
    Foo(TimeSpan.FromSeconds(2.0));
}
void Foo(TimeSpan span)
{
    //...
}

This works fine:

void Foo(TimeSpan span = default(TimeSpan))

Note: default(TimeSpan) == TimeSpan.Zero


The set of values which can be used as a default value are the same as can be used for an attribute argument. The reason being that default values are encoded into metadata inside of the DefaultParameterValueAttribute.

As to why it can't be determined at compile time. The set of values and expressions over such values allowed at compile time is listed in official C# language spec:

C# 6.0 - Attribute parameter types:

The types of positional and named parameters for an attribute class are limited to the attribute parameter types, which are:

  • One of the following types: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
  • The type object.
  • The type System.Type.
  • An enum type.
    (provided it has public accessibility and the types in which it is nested (if any) also have public accessibility)
  • Single-dimensional arrays of the above types.

The type TimeSpan does not fit into any of these lists and hence cannot be used as a constant.


void Foo(TimeSpan span = default(TimeSpan))
{
    if (span == default(TimeSpan)) 
        span = TimeSpan.FromSeconds(2); 
}

provided default(TimeSpan) is not a valid value for the function.

Or

//this works only for value types which TimeSpan is
void Foo(TimeSpan span = new TimeSpan())
{
    if (span == new TimeSpan()) 
        span = TimeSpan.FromSeconds(2); 
}

provided new TimeSpan() is not a valid value.

Or

void Foo(TimeSpan? span = null)
{
    if (span == null) 
        span = TimeSpan.FromSeconds(2); 
}

This should be better considering chances of null value being a valid value for the function are rare.


TimeSpan is a special case for the DefaultValueAttribute and is specified using any string that can be parsed via the TimeSpan.Parse method.

[DefaultValue("0:10:0")]
public TimeSpan Duration { get; set; }