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

cry*_*eam 6 .net c# 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));
}
Run Code Online (Sandbox Code Playgroud)

问题是,反序列化之前,我需要知道 T是对象还是对象列表.如何检查泛型方法中的内容?因为resharper给了我警告,我似乎无法解决这个问题.


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

在此先感谢您的帮助.

Med*_*o42 12

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

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

而Resharper是对的.该is运营商检查是否左边的情况下在右边的类型,所以在你的情况下,它会检查,如果typeof(T)是的一个实例List<object>.但是,typeof(T)返回表示类型的Type实例.检查的正确方法(如果你是在确切类型之后)将是T

if (typeof(T) == typeof(List<object>))
Run Code Online (Sandbox Code Playgroud)

但要注意的是,如果这仅适用T完全相同 List<object>.如果拥有子类型List<object>也可以,那么该行就是

if (typeof(List<object>).IsAssignableFrom(typeof(T)))
Run Code Online (Sandbox Code Playgroud)

但是你的问题并没有就此结束.您似乎认为这List<object>是所有列表的超类型.事实并非如此,即使我们可以假设我们只会使用List<T>列表的实现.对此的共鸣List<T>不变的.

不变性意味着猫的列表不是哺乳动物的列表.如果这看似违反直觉,那是因为您将列表视为您想要读取的固定集合.但是,您也可以将新项目添加到C#列表中,如果您被允许将a处理List<Cat>为a,List<Mammal>您最终可能会尝试将大象添加到该列表中,这将导致任何其他仍然持有引用该列表作为List<Cat>.

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

typeof(T).GetGenericTypeDefinition() == typeof(List<>)
Run Code Online (Sandbox Code Playgroud)

最后一点,以下代码看起来也很糟糕:

var deserialized = Deserialize<List<T>>(file);
Run Code Online (Sandbox Code Playgroud)

你搞清楚这T是真的List<Something>,所以你现在试图将你的文件反序列化为一个List<List<Something>>,这可能不是你想要的.


Ham*_*jam 6

您可以轻松检查

if (typeof(T).Name == "List`1")
{
    // T is a generic list
}
Run Code Online (Sandbox Code Playgroud)

正如drf提到的,不依赖内部实现的更好方法是:

if (typeof(T).GetGenericTypeDefinition() == typeof(List<>))
{
    // T is a generic list
}
Run Code Online (Sandbox Code Playgroud)

  • 或者等效地,`typeof(T).GetGenericTypeDefinition() == typeof(List&lt;&gt;)` (5认同)