多次调用 MakeGenericType(...) 是否每次都创建一个新类型?

Does calling MakeGenericType(...) multiple times create a new type every time?

我有一个 Entity Framework Code First 模型,我为此创建了一个静态泛型 class,它有一个搜索方法,列表中的每个项目都会被调用。 承认这超出了我的理解范围,我认为将 class 设为静态会提高代码的清晰度,甚至可能提高性能,因为不必在许多不同的地方创建实例。 所有这一切的目标是使用户可以自动搜索、导出哪些属性。

主要问题是:如果为具有引用类型 属性 的每个项目(可能是 1000 个)调用 MakeGenericType(...),那么该引用类型是通用类型 属性生成一次并保存在某处或生成 1000 次?

感谢指出任何其他性能犯罪或代码异味。

public static class SearchUserVisibleProperties<T>
{
    private static List<PropertyInfo> userVisibleProperties { get; set; }

    static SearchUserVisibleProperties()
    {
        userVisibleProperties = typeof(T).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(UserVisibleAttribute))).ToList();
    }

    public static bool search(T item, string searchString)
    {
        foreach (PropertyInfo pInfo in userVisibleProperties)
        {
            object value = pInfo.GetValue(item);
            if (value == null)
            {
                continue;
            }
            if (pInfo.PropertyType == typeof(string) || pInfo.PropertyType.IsValueType)
            {
                ...unrelevant string matching code...
            }
            else if ((bool)typeof(SearchUserVisibleProperties<>).MakeGenericType(new Type[] { value.GetType() }).InvokeMember(nameof(search), BindingFlags.InvokeMethod, null, null, new object[] { value, searchString }))
            {
                return true;
            }
        }
        return false;
    }
}

Documentation of MakeGenericType 建议泛型类型定义和泛型类型参数的相同组合返回的类型相同:

The Type object returned by MakeGenericType is the same as the Type obtained by calling the GetType method of the resulting constructed type, or the GetType method of any constructed type that was created from the same generic type definition using the same type arguments.

这里有一个小实验来证明以上是正确的:

var a = typeof(Tuple<,>).MakeGenericType(typeof(int), typeof(char));
var b = typeof(Tuple<,>).MakeGenericType(typeof(int), typeof(char));
var c = typeof(Tuple<int,char>);
Console.WriteLine(ReferenceEquals(a, b)); // True
Console.WriteLine(ReferenceEquals(a, c)); // True