我已经创建了这个简单的通用接口:
public interface IInitializerSettings<in ViewerType> where ViewerType : Component
{
void Apply(ViewerType dataViewer);
}
并为其添加了一个实现:
public class MenuSettings : IInitializerSettings<CustomGridLayout>
{
public void Apply(CustomGridLayout dataViewer)
{
Debug.Log("Applied");
}
}
public class CustomGridLayout : CustomLayout
{
// The implementation code
}
现在,我尝试像这样使用它:
public IInitializerSettings<CustomLayout> GetDefaultSettings()
{
return new MenuSettings();
}
但是我收到此错误“无法将类型MenuSettings转换为返回类型IInitializerSettings”
我不明白为什么不允许这样做,CustomGridLayout
继承了CustomLayout
。
我只能找到this question,但是这种解决方案对我不起作用(我不能使用out
关键字)。
答案 0 :(得分:3)
之所以不能这样做,是因为对于一个互逆接口(通过对通用类型参数使用in
指定),您不能将其隐式转换为派生类型较少的实例。如果您以IEnumerable<T>
(协变)和Action<T>
(相反)的角度来看,我认为要点in the docs可以解释得很好。
正如塞尔文在评论中提到的,Apply
中的MenuSettings
方法期望一个CustomGridLayout
的实例,因此无法尝试将MenuSettings
转换为IInitializerSettings<CustomLayout>
因为public void Apply(CustomGridLayout dataViewer)
无法处理CustomLayout
作为输入。让我举个例子:
public class CustomLayout
{
public void SetupCustomLayout() { ... }
}
public class CustomGridLayout : CustomLayout
{
public void SetupGrid() { ... }
}
public class MenuSettings : IInitializerSettings<CustomGridLayout>
{
public void Apply(CustomGridLayout dataViewer)
{
dataViewer.SetupGrid();
}
}
// Later in the code...
var menuSettings = new MenuSettings();
// This cast is what GetDefaultSettings() is trying to do
var genericSettings = (IInitializerSettings<CustomLayout>)menuSettings;
var layout = new CustomLayout();
// Looking at the type of 'genericSettings' this following line should be possible
// but 'MenuSettings.Apply()' is calling 'dataViewer.SetupGrid()' which doesn't exist
// in 'layout', so 'layout' is not a valid input
genericSettings.Apply(layout);
因此,相对于the docs,您已经将IInitializerSettings<ViewerType>
定义为一个协变接口,但是正试图将其用作协变接口-这是不可能的。