【问题标题】:Setting a generic delegate to a class-level variable将泛型委托设置为类级变量
【发布时间】:2009-07-08 19:11:16
【问题描述】:

我遇到了一个我需要的额外问题:Using an IEnumerable<T> as a delegate return type

根据上述解决方案,建议如下:

class Example
{
    //the delegate declaration
    public delegate IEnumerable<T> GetGridDataSource<T>();

    //the generic method used to call the method
    public void someMethod<T>(GetGridDataSource<T> method)
    {
        method();
    }

    //a method to pass to "someMethod<T>"
    private IEnumerable<string> methodBeingCalled()
    {
        return Enumerable.Empty<string>();
    }

    //our main program look
    static void Main(string[] args)
    {
        //create a new instance of our example
        var myObject = new Example();
        //invoke the method passing the method
        myObject.someMethod<string>(myObject.methodBeingCalled);
    }
}

请注意,在 someMethod 中,调用了委托“method()”。无论如何设置一个稍后调用的类级委托?

即:

 class Example {
    //the delegate declaration
    public delegate IEnumerable<T> GetGridDataSource<T>();

    //this fails because T is never provided
    private GetGridDataSource<T> getDS;

    //the generic method used to call the method
    public void someMethod<T>(GetGridDataSource<T> method)
    {
        getDS = method;
    }

    public void anotherMethod() {
        getDS();
    }
 }

【问题讨论】:

    标签: asp.net c#-3.0 delegates


    【解决方案1】:

    根据您要实现的目标以及您在设计中的灵活性,有多种选择。我已尝试涵盖我认为最有可能与您想做的事情相关的内容。

    非泛型类的单个实例中的多个 T 值

    这基本上就是您想要的。但是,由于方法调用的通用性,您需要一个可以支持T 的任何可能值的类级别变量,并且在为委托存储值时需要知道T

    因此,您可以使用Dictionary&lt;Type, object&gt;,也可以使用封装类级变量和方法的嵌套类型,然后改用List&lt;WrapperType&lt;T&gt;&gt;

    然后您需要根据所需类型查找适当的委托。

    class Example {
        //the delegate declaration
        public delegate IEnumerable<T> GetGridDataSource<T>();
    
        //this works because T is provided
        private Dictionary<Type, object> getDSMap;
    
        //the generic method used to call the method
        public void someMethod<T>(GetGridDataSource<T> method)
        {
            getDSMap[typeof(T)] = method;
        }
    
        //note, this call needs to know the type of T
        public void anotherMethod<T>() {
            object getDSObj = null;
            if (this.getDSMap.TryGetValue(typeof(T), out getDSObj))
            {
                GetGridDataSource<T> getDS = getDSObj as GetGridDataSource<T>;
                if (getDS != null)
                  getDS();
            }
        }
    

    非泛型类的单个实例中 T 的单个值

    在这种情况下,您可以将委托实例存储在非类型委托中,然后在需要时将其转换为适当的类型,并且您知道 T 的值。当然,您需要知道 T您首先创建委托,这首先消除了对泛型方法或委托的需求。

    泛型类的多个实例中的多个 T 值

    在这里,您可以使您的父类通用并预先提供 T。这将使您的示例正常工作,因为从一开始就知道 T 的类型。

    class Example<T> {
        //the delegate declaration
        public delegate IEnumerable<T> GetGridDataSource<T>();
    
        //this works because T is provided
        private GetGridDataSource<T> getDS;
    
        //the generic method used to call the method
        public void someMethod<T>(GetGridDataSource<T> method)
        {
            getDS = method;
        }
    
        public void anotherMethod() {
            if (getDS != null)
              getDS();
        }
     }
    

    【讨论】:

      【解决方案2】:

      您要么需要将类型设为泛型,要么使用普通的Delegate 并在需要调用它时转换回正确的类型。您不能只在泛型上下文之外使用 T - 编译器会认为您正在尝试引用名为 T 的普通类型。

      换句话说 - 如果您要尝试在两个不同的地方使用相同的类型 T,您将需要知道 T 在类型中的某个位置......并且如果类型不是通用的,那么该信息将存在于哪里?

      【讨论】:

        猜你喜欢
        • 2015-11-07
        • 1970-01-01
        • 2023-01-26
        • 2014-12-07
        • 1970-01-01
        • 1970-01-01
        • 2018-12-01
        • 1970-01-01
        • 2011-01-16
        相关资源
        最近更新 更多