c#-4.0 - C# 通用接口类型返回 Null
问题描述
我有一个类Table
,它返回一个集合Entity
,例如:
Table<Song> table = database.GetTable("SongCollection");
Song
子类在哪里Entity
。Table
还实现了一个接口ITable
并Entity
实现了一个名为IEntity
.
但是,调用:
ITable<IEntity> table = database.GetTable("SongCollection");
或者
ITable<Entity> table = database.GetTable("SongCollection");
或者
Table<Entity> table = database.GetTable("SongCollection");
或者
Table<IEntity> table = database.GetTable("SongCollection");
全部返回null。
我可以调用table.GetAll()
并返回 aList<Song>
并将每个人都投射Song
到一个IEntity
就好了。
在这种情况下我应该怎么做,Table
这样我就不必返回 aList<dynamic>
来获得Table
例如一个管理接口,以便对所有Tables
通用进行 CRUD 操作?
解决方案
这个问题的解决方案实际上很奇怪,感谢 Igor 帮助我朝着正确的方向前进。
因此,我确实将输出类型从代码更改List<T>
为IEnumerable<T>
没有任何重大故障,我的最终界面看起来像这样:
public interface ITable<out T> where T : IEntity {
string TableName { get; set; }
Database CurrentDatabase { get; set; }
T New();
T Get(ulong id);
IEnumerable<T> GetAll();
void LoadAllStorageFiles(IEnumerable<IEntity> storage);
void StoreAllStorageFiles(IEnumerable<IEntity> storage);
void LoadRelated(IEntity current);
void LoadRelated(IEnumerable<IEntity> current);
}
当我将 Covariant 方法和 Invariant(最初是逆变)方法分离为不同的接口类型时,协变将强制转换,而逆变将在强制转换期间变为 null。
这是奇怪的部分,这些是我原来的逆变方法:
void LoadAllStorageFiles(IEnumerable<T> storage);
void StoreAllStorageFiles(IEnumerable<T> storage);
void LoadRelated(T current);
void LoadRelated(IEnumerable<T> current);
现在您会认为使输入更加严格以仅接受与 Table 其余部分相同的泛型类型将具有隐含意义。但在这种情况下,在运行时它被视为逆变,运行时只是放弃并给你 null 没有例外。在这种情况下,将参数设置为 LoadRelated 等 IEntity 而不是 T,无论 Twilight Zone'ish 有多严格,因为现在参数已向任何 IEntity 开放,这似乎是我认为表明在某些逆变情况下,可能应该对运行时环境进行一些假设性的例外处理,但可能会花费更多的代码、精力和金钱来解决这样的问题,满足运行时环境的检查并且你能够继续前进。
所以我在这里只为遇到这种情况并耸耸肩的其他人注意。也许有人可以在评论中阐明一些观点。
推荐阅读
- testing - WidgetTest 导航随着 mockito 不工作而颤动
- javascript - React bootstrap NavBar 未编译
- typescript - 在 TypeScript 中限制数组的值
- c# - 每次尝试/捕获的 Xamarin.iOS Crashlytics 崩溃报告
- powershell - Powershell '获取存储的凭据'
- javascript - 用 Js 播放完一个又一个的音频
- java - 如何在 IntellIJ 控制台 (2019.3) 中使用 ANSI 颜色输出?
- c++ - 可以根据其值在编译时/运行时对 std::tuple 进行排序吗
- python - 如何在 pip 中修改 gcc 命令
- r - 按不同的降序排列数字