I'm working with a class library called DDay ICal. It is a C# wrapper for the iCalendar System implemented in Outlook Calendars, and many many many more systems. My question is derived from some work I was doing with this system.
There are 3 objects in question here
IRecurrencePattern: Not all code is shown
public interface IRecurrencePattern { string Data { get; set; } }
RecurrencePattern: Not all code is shown
public class RecurrencePattern : IRecurrencePattern { public string Data { get; set; } }
DbRecurPatt: Not all code is shown
public class DbRecurPatt { public string Name { get; set; } public string Description { get; set; } public static implicit operator RecurrencePattern(DbRecurPatt obj) { return new RecurrencePattern() { Data = $"{Name} - {Description}" }; } }
The confusing part: Through out DDay.ICal system they are using IList
s to contain a collection of Recurrence patterns for each event in the calendar, the custom class is used to fetch information from a database and then it is cast to the Recurrence Pattern through the implicit type conversion operator.
But in the code, I noticed it kept crashing when converting to the List<IRecurrencePattern>
from a List<DbRecurPatt>
I realized that I needed to convert to RecurrencePattern
, then Convert to IRecurrencePattern
(as there are other classes that implement IRecurrencePattern
differently that are also included in the collection
var unsorted = new List<DbRecurPatt>{ new DbRecurPatt(), new DbRecurPatt() }; var sorted = unsorted.Select(t => (IRecurrencePattern)t);
The above code does not work, it throws an error on IRecurrencePattern
.
var sorted = unsorted.Select(t => (IRecurrencePattern)(RecurrencePattern)t);
This does work tho, so the question I have is; Why does the first one not work? (And is there a way to improve this method?)
I believe it might be because the implicit operator is on the RecurrencePattern
object and not the interface, is this correct? (I'm new to interfaces and implicit operators)
Overview. Implicit type conversion in C language is the conversion of one data type into another datatype by the compiler during the execution of the program. It is also called automatic type conversion.
Implicit type conversion in C happens automatically when a value is copied to its compatible data type. During conversion, strict rules for type conversion are applied. If the operands are of two different data types, then an operand having lower data type is automatically converted into a higher data type.
There are two types of conversion: implicit and explicit. The term for implicit type conversion is coercion. Explicit type conversion in some specific way is known as casting. Explicit type conversion can also be achieved with separately defined conversion routines such as an overloaded object constructor.
Type conversion happens when we assign the value of one data type to another. If the data types are compatible, then C# does Automatic Type Conversion. If not comparable, then they need to be converted explicitly which is known as Explicit Type conversion. For example, assigning an int value to a long variable.
You have basically asked the compiler to do this:
DbRecurPatt
IRecurrencePattern
The compiler, even though it may only have one choice, does not allow you to do this. The cast operator specifically says that DbRecurPatt
can be converted to a RecurrencePattern
, not to a IRecurrencePattern
.
The compiler only checks if one of the two types involved specifies a rule on how to convert from one to the other, it does not allow intermediary steps.
Since no operator has been defined that allows DbRecurPatt
to be converted directly to IRecurrencePattern
, the compiler will compile this as a hard cast, reinterpreting the reference as a reference through an interface, which will fail at runtime.
So, the next question would be this: How can I then do this? And the answer is you can't.
The compiler does not allow you to define a user-defined conversion operator to or from an interface. A different question here on Stack Overflow has more information.
If you try to define such an operator:
public static implicit operator IRecurrencePattern(DbRecurPatt obj) { return new RecurrencePattern() { Data = $"{obj.Name} - {obj.Description}" }; }
The compiler will say this:
CS0552
'DbRecurPatt.implicit operator IRecurrencePattern(DbRecurPatt)': user-defined conversions to or from an interface are not allowed
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