代码之家  ›  专栏  ›  技术社区  ›  KalC

在非默认结构构造函数内调用结构方法

c#
  •  2
  • KalC  · 技术社区  · 15 年前

    我有一个非常简单的例子,用来学习C中的结构:

    struct ScreenPosition
    {
        // These are the two private members of the structure 
        private int x; 
        private int y;
    
        private int RangeCheckedX(int xPos)
        {
            if (xPos < 0 || xPos > 1280)
            {
                throw new ArgumentOutOfRangeException("X");
            }
            return xPos;
        }
    
        private int RangeCheckedY(int yPos)
        {
            if (yPos < 0 || yPos > 1024)
            {
                throw new ArgumentOutOfRangeException("Y");
            }
            return yPos;
        }
    
        // Declaring the non-default constructor
        public ScreenPosition(int X, int Y)
        {
            this.x = RangeCheckedX(X); // ERROR HERE
            this.y = RangeCheckedY(Y); // ERROR HERE
        }
    
        // Declaring  the property X - Follows a syntax. See the C# quick reference sheet 
        public int X
        {
            get
            {
                return this.x;
            }
    
            set
            {
                this.x = RangeCheckedX(value);
            }
        }
        // Declaring  the property X - Follows a syntax. See the C# quick reference sheet 
        public int Y
        {
            get
            {
                return this.y;
            }
    
            set
            {
                this.y = RangeCheckedY(value);
            }
        }
    }
    

    我在“此处出错”注释行中收到此错误:

    在将“this”对象的所有字段分配给之前,不能使用该对象

    在非默认构造函数中调用结构方法来为结构成员赋值是否非法?

    4 回复  |  直到 13 年前
        1
  •  5
  •   GBegen    14 年前

    您可以将这些方法设置为静态的,并且它可以工作,但是在分配所有字段之前,不能调用非静态方法。

        2
  •  2
  •   Blounty    15 年前

    在填充所有字段(属性)之前,不允许对结构调用方法。

    我知道这是个骗局,但这会奏效的。

     struct ScreenPosition
    {
        // These are the two private members of the structure 
        private int x;
        private int y;
    
        private int RangeCheckedX(int xPos)
        {
            if (xPos < 0 || xPos > 1280)
            {
                throw new ArgumentOutOfRangeException("X");
            }
            return xPos;
        }
    
        private int RangeCheckedY(int yPos)
        {
            if (yPos < 0 || yPos > 1024)
            {
                throw new ArgumentOutOfRangeException("Y");
            }
            return yPos;
        }
    
        // Declaring the non-default constructor
        public ScreenPosition(int X, int Y)
        {
            this.x = X; 
            this.y = Y; 
            this.x = RangeCheckedX(X);
            this.y = RangeCheckedY(Y);
        }
    
        // Declaring  the property X - Follows a syntax. See the C# quick reference sheet 
        public int X
        {
            get
            {
                return this.x;
            }
    
            set
            {
                this.x = RangeCheckedX(value);
            }
        }
        // Declaring  the property X - Follows a syntax. See the C# quick reference sheet 
        public int Y
        {
            get
            {
                return this.y;
            }
    
            set
            {
                this.y = RangeCheckedY(value);
            }
        }
    }
    
        3
  •  2
  •   Jon Skeet    15 年前

    gbegen有正确的想法-使范围检查方法静态化。

    这不仅可以解决问题,而且可以使代码更清晰:方法根本不依赖于结构的状态,也不具有多态性,因此它们不应该是实例方法。

        4
  •  1
  •   Jeffrey L Whitledge    15 年前

    在验证输入之前,可以将每个字段设置为零。这是有意义的,因为默认的构造程序无论如何都会将它们设置为零,所以这是一个无论如何都必须在程序中处理的情况。一旦设置了这些值,就可以调用任何您想要的方法,甚至在构造函数中也是如此。

    但正确的解决方案是其他人都在说的:让范围检查静态方法。事实上,在这种情况下,它们是纯函数(没有副作用,只在参数上操作,而不是静态或实例字段)。纯函数总是静态的。从调试、多线程、性能等方面来看,静态纯函数都是巧克力棒的。