I have got a struct:
public struct Decibel
{
public readonly double Value;
public Decibel (double value)
{
Value = value;
}
public static implicit operator Decibel (double decibels)
{
return new Decibel (decibels);
}
public static implicit operator double (Decibel decibels)
{
return decibels.Value;
}
}
And now I can do:
bool x = new Decibel (0) < new Decibel (1);
It seems the compiler is smart enough to convert Decibel
to double
, and then use the <
operator for doubles?
I had different struct
named Duration
, which was wrapping TimeSpan
. It had implicit conversions for TimeSpan
to/from Duration
, but the <
and >
operators are not working for it.
Does c# only recognize conversion between primitive types?
Implicit conversion is the conversion in which a derived class is converted into a base class like int into a float type. Explicit conversion is the conversion that may cause data loss. Explicit conversion converts the base class into the derived class.
We cannot perform implicit type casting on the data types which are not compatible with each other such as: Converting float to an int will truncate the fraction part hence losing the meaning of the value. Converting double to float will round up the digits.
Implicit conversions For example, a variable of type long (64-bit integer) can store any value that an int (32-bit integer) can store. In the following example, the compiler implicitly converts the value of num on the right to a type long before assigning it to bigNum .
Answer: Cast and Convert.
Firstly note that C# will allow a maximum of ONE implicit user-defined conversion between types.
So when you compare two instances of Decibel
, the compiler sees that it can use a user-defined implicit conversion to convert a Decibel
to a double
with which to compare.
However when you compare two instances of Duration
, the compiler cannot find any single implicit conversion which it can use to allow the comparison. The compiler will not consider any user-defined comparison operators for any of the types to which the type can be implicitly converted. It will only look for built-in comparison operators for any of the types to which the type can be implicitly converted.
Therefore the compiler will not use the implicit conversion to TimeSpan
, even though TimeSpan
provides a user-defined comparison operator that could theoretically be used.
Also note that even if the TimeSpan
class provided an implicit conversion to double
, the compiler would still not use it, since it will only consider at most one implicit user-defined conversion in the chain of implicit conversions.
In other words, given these structs:
public struct Number
{
public readonly double Value;
public Number(double value)
{
Value = value;
}
public static implicit operator Number(double duration)
{
return new Number(duration);
}
public static implicit operator double(Number number)
{
return number.Value;
}
}
public struct NumberWrapper
{
public readonly Number Value;
public NumberWrapper(Number value)
{
Value = value;
}
public static implicit operator NumberWrapper(Number duration)
{
return new NumberWrapper(duration);
}
public static implicit operator Number(NumberWrapper number)
{
return number.Value;
}
}
This code will compile:
bool x = new Number(1) < new Number(2);
And so of course will this:
Number n1 = new NumberWrapper(1);
Number n2 = new NumberWrapper(2);
bool z = n1 < n2;
But this won't:
bool y = new NumberWrapper(1) < new NumberWrapper(2);
because NumberWrapper
doesn't have an implicit conversion to any type that supports <
without any further implicit conversions.
Note that all primitive numeric and enumeration types (e.g. char, short, int, long, float, double, decimal, enum) provide built-in comparison operators. All other types can only provide user-defined comparison operators.
User-defined comparison operators look like this:
public static bool operator < (MyType lhs, MyType rhs) ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With