代码之家  ›  专栏  ›  技术社区  ›  David Ebbo

使用动态变量时是否可以指定通用参数?

  •  4
  • David Ebbo  · 技术社区  · 15 年前

    请考虑以下代码:

    class Program {
        void Foo<T>() { }
    
        static void Main(string[] args) {
            dynamic p = new Program();
            p.Foo();
        }
    }
    

    请注意,对p.foo()的调用是无效的,因为动态绑定器无法知道要为t使用什么类型。具体的失败是:

    无法从用法中推断方法“consoleapplication1.program.foo()”的类型参数。尝试显式指定类型参数。

    现在我的问题是: 是否有指定泛型类型的方法,或者使用“dynamic”不能调用此类方法?

    4 回复  |  直到 15 年前
        1
  •  14
  •   Jon Skeet    15 年前

    正如Jared所说,您可以在代码中指定它,就像静态调用一样:

    using System;
    
    class Program {
        void Foo<T>() {
            Console.WriteLine(typeof(T));
        }
    
        static void Main(string[] args) {
            dynamic p = new Program();
            p.Foo<string>();
        }
    }
    

    以上代码打印 System.String .

    现在如果你只知道 T 执行 时间,有点难。如果您有它的一个实例,那么您可以同时使用动态类型和类型推断:

    using System;
    
    class Program {
        void Foo<T>() {
            Console.WriteLine(typeof(T));
        }
    
        static void Main(string[] args) {
            dynamic p = new Program();
            dynamic v = GetRandomInstance();
    
            // Now to call p.Foo<T> where T is the type of v's value...
            Dummy(v, p);
        }
    
        static void Dummy<T>(T t, Program p) {
            p.Foo<T>();
        }
    
        static object GetRandomInstance() {
            return DateTime.Now.Hour > 10 ? "hello" : (object) 10;
        }
    }
    

    编辑:帕维尔在评论中提出了一个惊人的想法。你不需要想出一个 T ,只是一个数组。这意味着您甚至可以在通常无法使用的情况下使用类型参数 得到 一个实例 T (例如,由于私人建造商的原因):

    using System;
    
    class PrivateConstructor {
        private PrivateConstructor() {}
    }
    
    class Program {
        static void Foo<T>() {
            Console.WriteLine(typeof(T));
        }
    
        static void CallFooProxy<T>(T[] array) {
            Foo<T>();
        }
    
        static void CallFoo(Type t) {
            dynamic array = Array.CreateInstance(t, 0);
            CallFooProxy(array);
        }
    
        static void Main(string[] args) {
            CallFoo(typeof(PrivateConstructor));
        }
    }
    

    在有人问之前-不,这不允许你打电话 Foo<Enumerable> 动态-您仍然不能将静态类用作类型参数,即使您尝试将尝试延迟到执行时间:)

    如果因为某种原因所有这些都失败了,那么它又回到了正常的状态…获取方法信息,调用 MakeGenericMethod 并调用它。

        2
  •  2
  •   JaredPar    15 年前

    为什么不像对非动态类型那样指定类型呢?

    p.Foo<int>();
    
        3
  •  1
  •   Reed Copsey    15 年前

    在这种情况下,不管“p”是什么类型,您是否声明它为 动态 或作为 程序 ,您将收到此错误。

    错误是说无法推断t的类型,因为没有 参数 类型不是传递给方法的,并且该方法不是泛型类的一部分。在这种情况下,编译器无法推断T类型是什么。

    不过,您应该能够执行以下操作:

    class Program {
        void Foo<T>() { }
    
        static void Main(string[] args) {
            dynamic p = new Program();
            p.Foo<int>();
        }
    }
    

    调用foo时只需要显式定义t的类型。

        4
  •  0
  •   dahlbyk    15 年前

    为什么你不能具体说明 T dynamic ?

    p.Foo<dynamic>();