C# 实例变量放置?

C# 实例变量放置?,c#,coding-style,C#,Coding Style,我只是有一个关于实例变量放置的小问题 例如: private void example_MouseMove(object sender, MouseEventArgs e){ //do stuff } c#中的鼠标移动事件一直在轮询。有时,我可能只想在鼠标位置完全移动到另一个像素时运行其中的代码。所以我要写下: private void example_MouseMove(object sender, MouseEventArgs e){ if (_prevMousePosit

我只是有一个关于实例变量放置的小问题

例如:

private void example_MouseMove(object sender, MouseEventArgs e){
    //do stuff
}
c#中的鼠标移动事件一直在轮询。有时,我可能只想在鼠标位置完全移动到另一个像素时运行其中的代码。所以我要写下:

private void example_MouseMove(object sender, MouseEventArgs e){
    if (_prevMousePosition == Cursor.Position) return;
    //Do stuff
}
我的问题是:变量“_prevMousePosition”是否像往常一样位于类的顶部,还是直接位于方法的顶部,如下所示:

private Point _prevMousePosition = new Point(0, 0);
private void example_MouseMove(object sender, MouseEventArgs e){
    if (_prevMousePosition == Cursor.Position) return;
    //Do stuff
}
我觉得它应该放在方法的顶部,因为它将被访问的唯一位置是事件,并且它在方法之外的唯一目的是保留以前的鼠标位置

另外,如果有其他方法可以在没有实例变量的情况下实现相同的功能,我很想知道

我的问题是:变量“_prevMousePosition”是否像往常一样位于类的顶部,还是直接位于方法的顶部,如下所示:

private Point _prevMousePosition = new Point(0, 0);
private void example_MouseMove(object sender, MouseEventArgs e){
    if (_prevMousePosition == Cursor.Position) return;
    //Do stuff
}
这纯粹是个人喜好。编译器不在乎你把它放在哪里。将其放在方法上方是完全有效的C#,不会引起任何问题


C#代码的最标准约定(包括由诸如之类的工具强制执行的约定)建议您将字段与所有其他字段一起放在类的顶部。这样做的好处是,您可以轻松浏览类并查看所有本地存储的数据,以及确保正确初始化等。

如果将其放入MouseMove事件中,一旦超出范围,就会丢失该值。它应该放在类级别上。

尤其要小心,不要让类字段为单个方法保留状态。考虑:

  • 创建一个单独的类来处理鼠标操作和保存状态(历史)
  • 给你的类一个单独类的私有实例
  • 订阅该实例上的某个方法以处理
    example.MouseMove
    事件
  • 在类中编写处理程序,订阅单独类实例上的更高级别事件
  • 这将避免决定在何处放置高度本地化的字段的问题


    例如:

    class MouseTracker
    {
        private Point _prevMousePosition = new Point(0, 0);
        //Maybe define some higher-level events here
        public event ... MouseMoveWithHistory;
        public void HandleMouseMove(object sender, MouseEventArgs e)
        {
            if (_prevMousePosition == Cursor.Position) return;
            //Do stuff
            //Trigger higher level events
        }
    }
    
    然后,在你的课堂上:

    private MouseTracker tracker = new MouseTracker();
    ...
    //in your constructor
    example.MouseMove += tracker.HandleMouseMove;
    tracker.MouseMoveWithHistory += tracker_SomeLocalHandler;
    

    与核心“实例变量放置?”问题无关

    “c#中的鼠标移动事件一直在轮询。有时,我可能只想在鼠标位置完全移动到另一个像素时运行其中的代码。”

    啊?!。。。它不会触发“部分像素”…如果是这样的话。当您有一个基于整像素的新位置时,它将激发。如果您离开表单,然后在同一点重新输入,或者如果焦点切换,然后返回,并且光标没有移动,则可能具有相同的位置。如果可能的话,可能还有其他情况……但是您是否实际测试过新位置与以前位置匹配的频率?我不确定您在做什么,但在我的系统中这种情况并不经常发生:

    public partial class Form1 : Form
    {
    
        public Form1()
        {
            InitializeComponent();
            this.MouseMove += new MouseEventHandler(example_MouseMove);
            listBox1.MouseMove += new MouseEventHandler(example_MouseMove);
            this.Shown += new EventHandler(Form1_Shown);
        }
    
        void Form1_Shown(object sender, EventArgs e)
        {
            _prevMousePosition = Cursor.Position;
        }
    
        private int counter = 0;
        private Point _prevMousePosition = new Point(0, 0);
        private void example_MouseMove(object sender, MouseEventArgs e)
        {
            if (_prevMousePosition == Cursor.Position)
            {
                counter++;
                listBox1.Items.Add(counter.ToString() + ": " + _prevMousePosition.ToString());
                listBox1.SelectedIndex = listBox1.Items.Count - 1;
            }
            else
            {
                _prevMousePosition = Cursor.Position;
                this.Text = _prevMousePosition.ToString();
            }
        }
    
    }
    

    它可以去任何地方。你喜欢哪一种?不过我还是建议保持一致。大多数人会把它和其他类变量一起放在顶部。你可以把它放在任何你喜欢的地方,除非你是为某个对此有明确指导方针的人工作。我个人会把它放在方法的顶部,因为这样更容易找到它,而不必滚动到代码的顶部。请注意,如果您发现自己想要像这样的“范围”字段将它们与特定方法关联,这可能表明“提取类”重构是有价值的。考虑这些方法和它们相关的助手字段是否逻辑上属于一个可以与你的主要类的总体职责隔离的责任单位。正确的答案是:是和不是。看我的答案……:)这两个例子都是在班级层面;它也没有在方法范围内。你知道,我认为它也会按每一个新像素触发,但似乎我错了。如果不检查新点,代码将持续触发,每当鼠标移动时,程序就会变慢(读取:冻结)。通过检查,它运行良好。其他原因导致它持续开火;MouseMove()事件不会轮询或激发部分像素…可能是您的代码导致它以某种方式持续激发,或者您的系统设置不太“正确”。如果默认情况下MouseMove()事件确实持续激发,只需处理事件而不触摸鼠标,应用程序的CPU使用率就会提高到100%。C#会在短期内被发展世界一笑置之。尝试创建一个新的空白项目,只需放置一个
    控制台以查看问题是否仍然存在。它不是连续触发的,而是在移动过程中多次触发的。老鼠一动不动,什么也没发生。如果我移动鼠标,事件将触发。可能事件中的代码比触发另一个事件花费的时间更长,从而导致挂起…解决此类问题的一个可能方法是等待鼠标停止移动一定时间后再执行代码,但如果鼠标在完成之前再次移动,也允许取消或暂停。这取决于你在做什么…谢谢,这很有帮助。