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".
CodePudding user response:
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();
}