首页 > 解决方案 > C# 通用接口类型返回 Null

问题描述

我有一个类Table,它返回一个集合Entity,例如:

Table<Song> table = database.GetTable("SongCollection");

Song子类在哪里EntityTable还实现了一个接口ITableEntity实现了一个名为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 操作?

标签: c#-4.0asp.net-core.net-standard

解决方案


这个问题的解决方案实际上很奇怪,感谢 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 开放,这似乎是我认为表明在某些逆变情况下,可能应该对运行时环境进行一些假设性的例外处理,但可能会花费更多的代码、精力和金钱来解决这样的问题,满足运行时环境的检查并且你能够继续前进。

所以我在这里只为遇到这种情况并耸耸肩的其他人注意。也许有人可以在评论中阐明一些观点。


推荐阅读