代码之家  ›  专栏  ›  技术社区  ›  dkackman

为什么这段代码会抱怨“泛型类型定义的arity”?

  •  12
  • dkackman  · 技术社区  · 14 年前

    我有一个通用类型:

    class DictionaryComparer<TKey, TValue> : IEqualityComparer<IDictionary<TKey, TValue>>
    

    以及将(应该)为给定字典类型创建此类实例的工厂方法。

        private static IEqualityComparer<T> CreateDictionaryComparer<T>()
        {
            Type def = typeof(DictionaryComparer<,>);
            Debug.Assert(typeof(T).IsGenericType);
            Debug.Assert(typeof(T).GetGenericArguments().Length == 2);
    
            Type t = def.MakeGenericType(typeof(T).GetGenericArguments());
    
            return (IEqualityComparer<T>)Activator.CreateInstance(t);
        }
    

    除去所有无关的东西——甚至这个代码也会抛出相同的异常。

    private static object CreateDictionaryComparer()
    {
        Type def = typeof(DictionaryComparer<,>);
    
        Type t = def.MakeGenericType(new Type[] { typeof(String), typeof(object) });
    
        return Activator.CreateInstance(t);
    }
    

    断言通过了,所以我知道 T 是泛型的,有两个泛型参数。与…的关系 MakeGenericType 但以下情况除外:

    提供的泛型参数数不等于泛型类型定义的arity。

    参数名称:实例化

    我过去做过这种事,我这辈子都搞不明白为什么这件事在这种情况下不起作用。(另外,我必须谷歌 arity )

    2 回复  |  直到 5 年前
        1
  •  13
  •   dkackman    14 年前

    明白了。

    我有 DictionaryComparer 声明为内部类。我只能假设 MakeGenericType 想做一个 Query<T>.DictionaryComparer<string,object> 没有提供 T .

    故障代码

    class Program
    {
        static void Main(string[] args)
        {
            var q = new Query<int>();
            q.CreateError();
        }
    }
    
    public class Query<TSource>
    {
        public Query()
        {    
        }
    
        public object CreateError()
        {
            Type def = typeof(DictionaryComparer<,>);
    
            Type t = def.MakeGenericType(new Type[] { typeof(String), typeof(object) });
    
            return Activator.CreateInstance(t);
        }
    
        class DictionaryComparer<TKey, TValue> : IEqualityComparer<IDictionary<TKey, TValue>>
        {
            public DictionaryComparer()
            {
            }
    
            public bool Equals(IDictionary<TKey, TValue> x, IDictionary<TKey, TValue> y)
            {
                if (x.Count != y.Count)
                    return false;
    
                return GetHashCode(x) == GetHashCode(y);
            }
    
            public int GetHashCode(IDictionary<TKey, TValue> obj)
            {
                int hash = 0;
                unchecked
                {
                    foreach (KeyValuePair<TKey, TValue> pair in obj)
                    {
                        int key = pair.Key.GetHashCode();
                        int value = pair.Value != null ? pair.Value.GetHashCode() : 0;
                        hash ^= key ^ value;
                    }
                }
                return hash;
            }
        }
    }
    
        2
  •  1
  •   Jarek    6 年前

    CLR为应用程序使用的每种类型创建一个内部数据结构。这些数据结构称为类型对象。具有泛型类型参数的类型称为开放类型,并且 clr不允许构造任何打开类型的实例 (类似于clr如何阻止构造接口类型的实例)。

    变化

    Type t = def.MakeGenericType(new Type[] { typeof(String), typeof(object) });
    

    Type t = def.MakeGenericType(new Type[] { typeof(TSource), typeof(String), typeof(object) });