c# - 使用字典和泛型创建嵌套的 JSON 可序列化对象结构时,.NET 中的 C# 协方差存在问题

标签 c# json dictionary generics covariance

我在使用字典和泛型在 C# 中创建嵌套对象结构时遇到一些问题(我使用的是 Visual Studio、.NET Framework 4.6+)

主要问题是 C# 字典中缺乏协变性。

我必须在 C# 中创建这个简单的(JSON 可序列化/反序列化)对象结构。我尝试用动物来解释......

public class AnimalCatalog
{
    public Dictionary<string, Animal> AnimalsDict { get; set; }   // key is the species name
}

public class Animal   // base class
{
    public string Species { get; set; }   // univocal
    public bool CanFly  { get; set; }
    public Dictionary<string, GenericPaw> PawsDict { get; set; }   // each animal has a different type and a different number of paws
}

public class GenericPaw   // base class
{
    public int FingerNumber { get; set; }   // number of finger in each paw
}

public class Cat : Animal   // derived class
{
    public void meow()   // only cats says 'meow'
    {...}
}

public class CatPaw : GenericPaw   // derived class
{
    public void scratch()   // cats paws could scratch something :) but not all the animals paws could
    {...}
}

我使用 C# 泛型实现了这个结构,因为 Cat 有一个 CatPaws 字典,而不是泛型 Paws :P。这是我的建议。

public class AnimalCatalog<T,V> where T : Animal<V> where V : GenericPaw 
{
    public Dictionary<string, T> AnimalsDict { get; set; } = new Dictionary<string, T>();  // key is the species name
}

public class Animal<T> where T : GenericPaw   // base class
{
    public string Species { get; set; }   // univocal
    public bool CanFly  { get; set; }
    public Dictionary<string, T> PawsDict { get; set; }   // each animal has a different type and a different number of paws
}

public class GenericPaw   // base class
{
    public string PawName { get; set; }   // univocal
    public int FingerNumber { get; set; }   // number of finger in each paw
}

public class Cat<T> : Animal<T> where T : CatPaw   // derived class
{
    public void meow()   // only cats says 'meow'
    {...}
}

public class CatPaw : GenericPaw   // derived class
{
    public void scratch()   // cats paws could scratch something :) but not all the animals paws could
    {...}
}

让我们使用创建的类<​​/p>

Cat<CatPaw> Kitty = new Cat<CatPaw>();   // create a cat
CatPaw KittyFirstPaw = new CatPaw();   // create the 1st cat's paw
Kitty.PawsDict.Add(KittyFirstPaw.PawName, KittyFirstPaw);   // add the paw to the dict
AnimalCatalog<Animal<GenericPaw>,GenericPaw> ZooCatalog = new AnimalCatalog<Animal<GenericPaw>,GenericPaw>();   // create a catalog of animals
Animal<GenericPaw> GenericAnimal = Kitty;   <-- doens't compile (can't convert derived to base class)
AnimalCatalog.AnimalsDict.Add(GenericAnimal.Species, GenericAnimal);

我还尝试使用接口(interface)而不是基类,使用 out 关键字将 T 指定为协变类型,但它不起作用,因为我无法在字典中使用协变类型...

非常感谢任何帮助:) 斯特凡诺

最佳答案

您无法转换Cat<CatPaw>Animal<GenericPow> ,因为这样您就可以添加不同类型的 GenericPaw进入它的字典(例如 DogPaw ),猫不会欣赏这一点。

这只是一个问题,因为您可以在字典中插入新值,因此似乎可以通过使用 IReadOnlyDictionary 来解决它,但不幸的是,由于 this question 中描述的技术问题,该值也不是协变的。 .

顺便说一句,有没有原因 Cat也是通用的吗?

public class Cat<T> : Animal<T> where T : CatPaw

如果您想创建一只只能拥有源自CatPaw的特定爪子的猫,这将很有用。 。如果没有,这可能会变成:

public class Cat : Animal<CatPaw>

AnimalCatalog似乎也不必要地复杂。如果您只需要 Animal 的动物目录,它可以简化为只有一个通用参数:

public class AnimalCatalog<TPaw> where TPaw : GenericPaw
{
    public Dictionary<string, Animal<TPaw>> AnimalsDict { get; set; }
}

如果您只需要 AnimalCatalog<GenericPaw> ,你也可以去掉这个参数。但这个目录仍然不是很有用,因为您无法转换 Animal<CatPaw>Animal<GenericPaw> .

为了解决这个问题,您可以创建 IAnimal<out TPaw> 的协变接口(interface)具有 Animal 的所有属性但除了字典之外,您还可以将爪子公开为 IEnumerable<TPaw> Paws如果您需要字典查找,可以使用以下方法:TPaw GetPaw(string pawName) 。这些将使用字典来实现。然后就可以转换 Cat (这是 Animal<CatPaw> ,因此也是 IAnimal<CatPaw> )到 IAnimal<GenericPaw> 。您的动物目录将包含 IAnimal<GenericPaw> .

关于c# - 使用字典和泛型创建嵌套的 JSON 可序列化对象结构时,.NET 中的 C# 协方差存在问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48060913/

相关文章:

python - 提取具有多个值的 : Python dictionary, 键

arrays - 使用字符串数组作为值在swift中创建字典

c# - 接口(interface)实现困惑

ios - 使用 AFNetworking 处理单个请求的多个 JSON 响应

java - 如何在java中使用map创建JSONArray

javascript - 如何序列化 blob javascript

c# - 在特定 OU Active Directory 中搜索用户

c# - 是否存在 TcpClient.Close 或 Socket.Close(0) 可能阻止我的代码的情况?

javascript - 从 Confluence 调用自定义 REST API

python - 字典似乎没有添加新键