c# - 如何检查 T 是否是泛型方法中的对象列表

标签 c# .net generics

我正在尝试编写一个通用方法,用于使用 Json.NET 从 json 文件反序列化
我希望能够支持反序列化包含对象和对象数组的文件。以下是我目前拥有的两种通用方法的简化版本:

/// <summary>   Deserializes object or an array of objects from a list of files. </summary>
public static List<T> Deserialize<T>(List<string> filePathsList)
{
    var result = new List<T>();
    foreach (var file in filePathsList)
        // HOW DO I FIND OUT IF T IS A LIST HERE?
        // Resharper says: the given expression is never of the provided type
        if (typeof(T) is List<object>)
        {
            var deserialized = Deserialize<List<T>>(file);
            result.AddRange(deserialized);
        }
        // Resharper says: Suspicious type check: there is not type in the solution
        // which is inherited from both 'System.Type' and 'System.Collections.IList'
        else if (typeof(T) is IList)
        {
            // deserializing json file with an array of objects
            var deserialized = Deserialize<List<T>>(file);
            result.AddRange(deserialized);
        }
        else
        {
            // deserializing a single object json file
            var deserialized = Deserialize<T>(file);
            result.Add(deserialized);
        }
    return result;
}


/// <summary>   Deserializes object or an array of objects from a file. </summary>
public static T Deserialize<T>(string filepath)
{
    return JsonConvert.DeserializeObject<T>(File.ReadAllText(filepath));
}

问题是,在反序列化之前,我需要知道 T 是对象还是对象列表。我如何在通用方法中检查它?因为 resharper 给我警告,而我似乎无法弄清楚。


编辑:我在示例代码中犯了一个错误,正如@Medo42 指出的那样,它会用 List<List<Something>> 调用 Deserialize() 另外,我根本不应该包含一个涉及 json 序列化的示例,它应该更通用。问题是关于查明 T 是否是一个对象列表。

在此先感谢您的帮助。

最佳答案

这不是一个完整的答案,但对于评论来说太长了,可能会帮助您更好地理解一些问题。

// Resharper says: the given expression is never of the provided type
if (typeof(T) is List<object>)

Resharper 是对的。 is运算符检查左侧的实例是否属于右侧的类型,因此在您的情况下,它检查是否 typeof(T)List<object> 的实例.然而,typeof(T)返回 Type 代表 T 类型的实例.正确的检查方法(如果你在寻找确切的类型)是

if (typeof(T) == typeof(List<object>))

但请注意,这仅适用于T正是 List<object> .如果子类型为 List<object> 也可以, 该行将是

if (typeof(List<object>).IsAssignableFrom(typeof(T)))

但是您的问题并没有就此结束。你似乎假设 List<object>是所有列表的父类(super class)型。事实并非如此,即使我们可以假设我们只会使用 List<T>列表的实现。这样做的原因是 List<T>不变的

不变性意味着猫的列表不是哺乳动物的列表。如果这看起来违反直觉,那是因为您将列表视为要从中读取的固定集合。但是,您也可以将新项目添加到 C# 列表中,如果允许您处理 List<Cat>作为List<Mammal>您最终可能会尝试将一头大象添加到该列表中,这将给仍然将该列表引用为 List<Cat> 的任何其他人带来无穷无尽的困惑。 .

对于类型检查问题的解决方案,我认为 drf 对 dotctor 的回答的评论是做你认为你想做的事情的最干净的方法:

typeof(T).GetGenericTypeDefinition() == typeof(List<>)

最后,下面的代码看起来也很奇怪:

var deserialized = Deserialize<List<T>>(file);

您在弄清楚 T 之后执行此操作真的是List<Something> ,因此您现在正尝试将文件反序列化为 List<List<Something>> ,这可能不是您想要的。

关于c# - 如何检查 T 是否是泛型方法中的对象列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34373340/

相关文章:

c# - 在 "delegate"中记录每个方法

java - 尝试在 Jersey 2.27 中绑定(bind)工厂类时出现编译错误

ios - 快速在通用类中实现协议(protocol)

c# - 在方法重载中使用 C# 泛型的问题

c# - 如果我不再关心结果,是否还有结束委托(delegate)的方法?

c# - 是否存在内存泄漏?

c# - 将附件添加到 MailMessage 时出现流关闭错误

c# - 当一切看起来都很好时,有条件的不起作用

c# - 使用 GetSaveFileName 创建 SaveFileDialog 时如何停止覆盖提示

c# - 为什么进程会丢失线程?