3

我是匿名课程的新手,今天我想我遇到了第一个我觉得我真的可以使用它们的案例。我正在编写一种方法,该方法可以从在类中存储临时数据中受益,并且由于该类在该方法之外没有任何意义,因此使用匿名类对我来说肯定是有意义的(至少在它这样做的时候) )。

在开始编码之后,我确实似乎不得不做出一些让步。我喜欢将诸如计算之类的东西分配给临时变量,以便在调试期间我可以一次验证逻辑块中的计算位。然后我想为最终值分配一些更简单的东西。该值将在匿名类中。

问题是为了简洁地使用匿名类实现我的代码,我想使用 LINQ。这里的问题是,我认为您不能在语句内部进行此类临时计算。 或者你可以吗?

这是我想做的一个人为的例子:

namespace AnonymousClassTest
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        ObservableCollection<RectanglePoints> Points { get; set; }

        public class RectanglePoints
        {
            public Point UL { get; set; }
            public Point UR { get; set; }
            public Point LL { get; set; }
            public Point LR { get; set; }
        }

        public class DontWantThis
        {
            public double Width { get; set; }
            public double Height { get; set; }
        }

        private Dictionary<string,string> properties = new Dictionary<string,string>();
        private Dictionary<string,double> scaling_factors = new Dictionary<string,double>();

        private void Sample()
        {
            // not possible to do temp variables, so need to have
            // longer, more unreadable assignments
            var widths_and_heights = from rp in Points
                                     select new
                                     {
                                        Width = (rp.UR.X - rp.UL.X) * scaling_factors[properties["dummy"]],
                                        Height = (rp.LL.Y - rp.UL.Y) * scaling_factors[properties["yummy"]]
                                     };

            // or do it in a for loop -- but then you have to use a concrete
            // class to deal with the Width and Height storage
            List<DontWantThis> other_widths_and_heights = new List<DontWantThis>();
            foreach( RectanglePoints rp in Points) {
                double base_width = rp.UR.X - rp.UL.X;
                double width_scaling_factor = scaling_factors[properties["dummy"]];
                double base_height = rp.LL.Y - rp.UL.Y;
                double height_scaling_factor = scaling_factors[properties["yummy"]];

                other_widths_and_heights.Add( new DontWantThis 
                                              { 
                                                  Width=base_width * width_scaling_factor,
                                                  Height=base_height * height_scaling_factor
                                              });
            }

            // now we want to use the anonymous class, or concrete class, in the same function
            foreach( var wah in widths_and_heights)
                Console.WriteLine( String.Format( "{0} {1}", wah.Width, wah.Height));
            foreach( DontWantThis dwt in other_widths_and_heights)
                Console.WriteLine( String.Format( "{0} {1}", dwt.Width, dwt.Height));
        }

        public Window1()
        {
            InitializeComponent();
            Points = new ObservableCollection<RectanglePoints>();
            Random rand = new Random();
            for( int i=0; i<10; i++) {
                Points.Add( new RectanglePoints { UL=new Point { X=rand.Next(), Y=rand.Next()  },
                                                  UR=new Point { X=rand.Next(), Y=rand.Next()  },
                                                  LL=new Point { X=rand.Next(), Y=rand.Next()  },
                                                  LR=new Point { X=rand.Next(), Y=rand.Next()  }
                                                } );
            }

            Sample();
        }
    }
}

注意:除非您实际将键添加到字典中,否则不要尝试运行它:)

在 LINQ 中创建匿名类很棒,但迫使我在一行中进行计算。想象一下,计算比我展示的要长得多。但它是相似的,我会做一些字典查找来获取特定的值。调试可能很痛苦。

具体类的使用解决了使用临时变量的问题,但是我不能简洁地做所有事情。是的,我意识到我说我正在寻找简洁性,同时要求能够在我的 LINQ 语句中保存临时变量,这有点矛盾。

在循环点时,我开始尝试创建一个匿名类,但很快意识到我无法存储它!您不能使用 List ,因为这只会失去班级的全部匿名性。

谁能建议一种方法来实现我正在寻找的东西?还是一些中间立场?我在 StackOverflow 上阅读了其他一些问题,但没有一个与我的完全相同。

4

2 回答 2

5

假设我理解正确,问题是您必须在一个表达式中设置所有属性。匿名类型绝对是这种情况。

但是,您不必在该表达式中全部内联。我建议,如果您的属性基于复杂的表达式,请将这些表达式分解为辅助方法:

var complex = new {
      First = ComputeFirstValue(x, y),
      Second = ComputeSecondValue(a, b)
      ...
};

如果您是白盒测试的粉丝(我是),这具有额外的潜在好处,您可以单独对每个辅助方法进行单元测试。

这不会避免存在一个大的匿名类型初始化表达式,但这意味着工作将被分解。

于 2010-08-10T16:37:35.983 回答
1

匿名类实际上是为了简化处理 lambdas 的东西,尤其是 LINQ。您尝试做的事情听起来更适合嵌套的私有类。这样,只有您的班级真正了解​​您的临时班级。尝试使用匿名类似乎只会使您的代码复杂化。

于 2010-08-10T16:44:24.443 回答