1

i made a small timeout struct and wanted to add conversion to make it a bit easier to use:

public struct TimeoutValue<T>
{
    public static TimeSpan DefaultTimeout { get; } = TimeSpan.FromSeconds(5);

    public DateTime CreationTime { get; set; } = DateTime.UtcNow;
    public TimeSpan? CustomTimeout { get; set; } = null;

    public T Value { get; set; }

    public readonly bool IsTimeouted => DateTime.UtcNow - CreationTime >= (CustomTimeout ?? DefaultTimeout);

    public TimeoutValue(T value) => Value = value;
    public TimeoutValue(DateTime creationTime, T value) : this(value) => CreationTime = creationTime;
    public TimeoutValue(TimeSpan customTimeout, T value) : this(value) => CustomTimeout = customTimeout;
    public TimeoutValue(DateTime creationTime, TimeSpan customTimeout, T value) : this(creationTime, value) => CustomTimeout = customTimeout;

    public static explicit operator T(TimeoutValue<T> value) => value.Value;
    public static implicit operator TimeoutValue<T>(T value) => new(value);
    public static implicit operator T?(TimeoutValue<T> value) => value.IsTimeouted ? null : value.Value;
}

however, the last one won't work.

the way it is now, because of the explicit operator, it says it's double and it won't accept to return null. it doesn't seem to realize, that it's supposed to be nullable.

but if i make it Nullable<T>, i can only put structs in it which defies the purpose of my struct. also i can't return value.Value then.

anyone ideas how i can make this work?

  • 1
    `T` and `T?` are considered the same type for generic types as far as method overloading is concerned, so you cannot make this work even if you fix the compile error because then the explicit `T()` and the implicit `T?()` operators will be considered to have the same signature. (But note that if you add `where T: struct` then they are NOT considered to be the same type, because then the underlying types are using `Nullable`.) – Matthew Watson Aug 01 '23 at 08:14
  • But as Mad Hatter points out, you can remove the duplicate method and use `where T: class` – Matthew Watson Aug 01 '23 at 08:20
  • you are right. without the explicit operator it works. thanks @MatthewWatson i didn't know they are treated as the same – cattle81194 Aug 01 '23 at 08:34
  • Does it work for you to have `public T? Value { get; set; }` and then do `public static implicit operator T?(TimeoutValue value) => value.IsTimeouted ? default(T) : value.Value;`? When I do that it compiles fine (after removing `public static explicit operator T(TimeoutValue value) => value.Value;`). – Enigmativity Aug 01 '23 at 08:53

1 Answers1

1

Is adding where T : class to your struct acceptable ? If this is the case you could keep only both implicit operators

public static implicit operator TimeoutValue<T>(T value) => new(value);
public static implicit operator T?(TimeoutValue<T> value) => value.IsTimeouted ? null : value.Value;
Mad hatter
  • 569
  • 2
  • 11