在运行时为访问List的元素分配公式

时间:2015-10-17 13:32:53

标签: c# for-loop lambda delegates action

场景是我说两种不同类型的案例 - 案例1和案例2.对于案例1和案例2,每个我都有一个startIndex,endIndex和一个用于访问List元素的公式。

现在分配值startIndex和endIndex我更喜欢普通的开关情况,但是我对于访问元素的公式感到茫然。对于案例1 ,可以说列表[a + i] ,对于案例2 ,则说列表[a +( IB)] 即可。     一种方法是像这样有一个for循环

for(int i=0;;i++)
{ 
     if(case is 1)
        then f=a+i 
     else if(case 2)
        then f=a+(i-b) 
}

我想过使用代表。但是,据我所知,他们需要成为全球性的。行动不会返回价值。可以使用Func,但是一个表达式/公式只需要一个元素(int)而另一个需要3.我需要在行中使用某些内容,就像匿名函数可以在运行时从switch case中分配任何上述公式(作为案件可能并且将来会增加。)

谢谢。

2 个答案:

答案 0 :(得分:0)

  

我想过使用代表。但是,根据我的知识,他们需要   成为全球性的。

事实并非如此(实际上,C#中没有真正的全局变量,因为每个变量都需要封装在一个对象中)。在引用包含此类型代码的程序集后,所有代码确实都可以看到公共委托 type ,但此类型的变量可以是私有的。

在您的情况下,我建议从案例编号到代理人进行某种映射。如果每个案例最多只有一个代表,那么最好使用Dictionary<TKey, TValue>。此字典可以作为私有变量存储在方法所在的类中。

public class MyClass
{
    private Dictionary<int, Delegate> _delegateMapping = new Dictionary<int, Delegate>;
}

有几种方法可以在构造函数中添加元素字典:传递已填充的字典,传递委托数组,在构造函数本身中创建这些委托。无论哪种方式,您最终都会得到Delegate类型的字典,因此您需要使用强制转换才能在代码中正确使用它们。

 for (int i = 1; i < _delegateMapping.Count; i++)
 {
     switch (i)
     {
         case 1:
             var f = (Action<int>)_delegateMapping[1];
             f(i);
             break;
         case 2:
             var f = (Action<int, int>)_delegateMapping[2];
             f(i, a);
             break;
     }
 }   

我当然非常即兴。

重要的是要注意,如果委托的类型在字典内发生变化,则必须在switch语句中相应地修改委托。否则,如果不存在隐式转换,您将获得运行时异常。

答案 1 :(得分:0)

大家好,非常感谢您的反馈意见。我终于找到了Func的解决方案。这就是我的代码。我不得不稍微操纵Func的用法。我在Func中使用了几乎所有的变量作为全局/局部函数来编写这些函数。如果我无法正确解释我的问题,我表示道歉。

        int i = -1;
        Func<int,int> formula = null;

        switch(f)
        {
            case 1:
            {
                formula = new Func<int,int>(index => { return i; });
            }
            break;

            case 2:
            {
                formula = new Func<int, int>( index => { return s- (i * c); } );//here s and c are global variables.
            }
            break;
        }
        i = startIndex;

        while(i < endIndex)
        {
            var Obj= List[formula.Invoke(i)];
            //my code goes here
            i++;
        }

让我知道我的解决方案是否正确w.r.t性能,逻辑,C#编程等。:)

EDITED :: @usr和@Kapol我尝试了你建议的方式,并尝试即兴创作这样的代码。

    private Dictionary<int, Func<int[], int>> indexFormulae;

    private void assignDelegates()
    {
        indexFormulae = new Dictionary<int, Func<int[], int>>();
        indexFormulae.Add(0, getFormula_1);
        indexFormulae.Add(1, getFormula_2);
    } 
    private void someFunction(int sp)
    {
        int i = 0;
        Func<int[], int> formula = null;
        indexFormulae.TryGetValue(formation,out formula);

        i = startIndex;
        while (i < endIndex)
        {
            int[] intValues = new int[] {i,sp,globalVar };
            var Obj = List[formula.Invoke(intValues)];
            //My code here
            i++;
        }
    }

    private int getFormula_1(params int[] intValues)
    {
        return intValues[0];
    }

    private int getIndex_Vertical(params int[] intValues)
    {
        return intValues[1] - (intValues[0] * intValues[2]); 
    }

所以,现在我可以在这个类的任何地方使用这两个getFormula方法,而不是保持匿名。而且我认为我会坚持使用params,因为将来可能会有其他函数的N个int参数。