public interface IBaseUiItem
{}
public interface IButton : IBaseUiItem
{}
public class ControlBase : IBaseUiItem
{}
public class Button : ControlBase, IButton
{}
public I GetOne<I>() where I : IBaseUiItem
{
return (I)(new Button());
}
public I GetTwo<I>() where I : IBaseUiItem
{
object f = new Button();
return (I)f;
}
In the above why GetOne() doesn't compile, but the GetTwo() does? In other words why the error in the first case is "Connot convert type Button to I"
I tried using "as" operator to see if it makes difference (without luck of course).
I guess, the GetOne cannot be compiled because saves you from a creation of an instance (new Button) that might not implement the interface type you supply to the method.
And also I understand the "object" being so general makes it a possible candidate for casting to any type.
And finally, the fact that there is no special interface-obtaining-operator doesn't allow the compiler to make proper usage of the generic, no matter if it is an "interface generic" and not "type generic".
In other words why the error in the first case is "Cannot convert type Button to I"
Because I
is not guaranteed to be Button
(or any interface which inherits IBaseUiItem
and is implemented by Button
) i.e. compiler prevents calls such as:
public class NotAButton : ControlBase, IButton {}
var x = GetOne<NotAButton>();
using object
as intermediate type disables this compiler check (as explicit conversion from object
and dynamic
to any other reference_type) and you will get runtime error:
GetTwo<NotAButton>();
System.InvalidCastException: Unable to cast object of type 'Button' to type 'NotAButton'.
If you want to be able to create a new instance of your generic you can use new
generic constraint:
I GetOne<I>() where I : IBaseUiItem, new()
{
return new();
}