将泛型委托设置为类级变量

时间:2009-07-08 19:11:16

标签: asp.net c#-3.0 delegates

我遇到了另外一个问题: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();
    }
 }

2 个答案:

答案 0 :(得分:2)

根据您要实现的目标以及设计的灵活性,有许多选择。我试图掩盖那些我认为最可能与你想做的事情有关的事情。

非泛型类

的单个实例中的T的多个值

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

因此,您可以使用Dictionary<Type, object>,也可以使用封装类级变量和方法的嵌套类型,然后使用List<WrapperType<T>>代替。

然后,您需要根据所需类型查找相应的委托。

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();
    }
 }

答案 1 :(得分:0)

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

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