C#结构编译错误

C#结构编译错误,c#,compiler-construction,struct,C#,Compiler Construction,Struct,这是一个家庭作业,我们不学习C#中的结构(我现在正在学习)。所以我去了msdn,但是我没有发现我的程序有什么问题。。。 是的,我不能完全翻译我的母语,我也不明白编译器的想法 我的作业的UML:(我们必须使用它) 接口:IComparable +分子{get;}:长 +分母{get;}:长 +有理数(分子:长,分母:长) +GCD(a:长,b:长):长 +等于(r:理性):布尔 我们不能实现其他方法或参数 我用Java编写了这个家庭作业,其中包含正确运行的类 我有一个大问题,我不明白以下错误

这是一个家庭作业,我们不学习C#中的结构(我现在正在学习)。所以我去了msdn,但是我没有发现我的程序有什么问题。。。 是的,我不能完全翻译我的母语,我也不明白编译器的想法

我的作业的UML:(我们必须使用它) 接口:IComparable

  • +分子{get;}:长
  • +分母{get;}:长
  • +有理数(分子:长,分母:长)
  • +GCD(a:长,b:长):长
  • +等于(r:理性):布尔
我们不能实现其他方法或参数

我用Java编写了这个家庭作业,其中包含正确运行的类

我有一个大问题,我不明白以下错误是什么意思:

错误2自动实现的属性“Rational.Rational.Denominator”的支持字段必须在控件返回给调用方之前完全赋值。考虑从构造函数初始化器调用默认构造函数。< /P> 错误3自动实现的属性“Rational.Rational.Numerator”的支持字段必须在控件返回给调用方之前完全赋值。考虑从构造函数初始化器调用默认构造函数。< /P> 错误4在将“this”对象的所有字段分配给之前,无法使用该对象

我的代码: 名称空间有理

{
    //       (Rational is underline)     here the 2 and 3 error
    public struct Rational : IComparable<Rational>
    {
        public long Numerator { get; set; }
        public long Denominator { get; set; }

        public Rational(long num, long den)
        {
             // and here (GCD is underline) the 4. error
            long simple = GCD(num, den);
            this.Numerator = num/simple;
            this.Denominator = den/simple;
        }

        public long GCD(long a, long b)
        {
            long c = Math.Abs(a);
            long d = Math.Abs(b);
            if (d == 0) return c;
            return GCD(d, c % d);
        }

        public override string ToString()
        {
            if (Denominator==1)
            {
                return Numerator + "";
            }
            return Numerator+"/"+Denominator;
        }

        public override bool Equals(object obj)
        {
            bool result = false;
            if (obj is Rational)
            {
                Rational r = (Rational)obj;
                result = this.Equals(r);
            }
            return result;            
        }

        public bool Equals(Rational r)
        {
            if ((object)r ==null)
            {
                return false;
            }
            return this.Denominator == r.Denominator && this.Numerator == r.Numerator;
        }

        public int CompareTo(Rational other)
        {
      ...
{
//(有理数下划线)这里是2和3错误
公共结构Rational:i可比较
{
公共长分子{get;set;}
公共长分母{get;set;}
公共Rational(长num,长den)
{
//这里(GCD是下划线)是4.错误
长简单=GCD(数量,单位);
这个。分子=num/简单;
这个。分母=den/简单;
}
公共长GCD(长a、长b)
{
长c=数学Abs(a);
长d=数学Abs(b);
如果(d==0)返回c;
返回GCD(d,c%d);
}
公共重写字符串ToString()
{
如果(分母=1)
{
返回分子+“”;
}
返回分子+“/”+分母;
}
公共覆盖布尔等于(对象对象对象)
{
布尔结果=假;
if(obj是理性的)
{
有理r=(有理)obj;
结果=这个。等于(r);
}
返回结果;
}
公共布尔等于(有理r)
{
如果((对象)r==null)
{
返回false;
}
返回this.densor==r.densor&&this.Numerator==r.Numerator;
}
公共整数比较(理性其他)
{
...

我在
Rational
的构造函数中注意到,您正在调用GCD并将结果存储在
simple
中,但您不使用结果。

您可以将
this()
添加到构造函数中,或者用字段支持的属性替换自动属性

 public Rational(long num, long den)
 {
         // and here (GCD is underline) the 4. error
        long simple = GCD(num, den);
        this.Numerator = num;
        this.Denominator = den;
 }
在为支持属性的自动生成字段指定值之前,您可以访问实例方法
GCD

您应该将此方法设置为静态

接下来,您将再次遇到相同的错误,这一次是因为您访问了自动属性
分子
。您可以通过保留自动属性并将
:this()
添加到构造函数来修复此错误:

 public Rational(long num, long den)
   :this()
 {
这将导致在您自己的构造函数代码运行之前,字段被初始化为
0

另一种选择是切换到字段:

public struct Rational : IComparable<Rational>
{
    private long _numerator;
    private long _denominator;

    public long Numerator { get{return _numerator;}; set{_numerator=value;} }
    public long Denominator{ get{return denominator;}; set{_denominator=value;} }

    public Rational(long num, long den)
    {
         // and here (GCD is underline) the 4. error
        long simple = GCD(num, den);
        this._numerator = num;
        this._denominator = den;
    }
public-struct-Rational:i可比较
{
私人长分子;
私人长分母;
公共长分子{get{return}分子;};集合{U分子=值;}
公共长分母{get{return deminator;};set{u deminator=value;}
公共Rational(长num,长den)
{
//这里(GCD是下划线)是4.错误
长简单=GCD(数量,单位);
这个。_分子=num;
这个。分母=den;
}

除此之外,您的代码几乎没有其他问题:

1) 您使用的是可变结构。这通常是糟糕的设计。请从属性中删除setter或将其设置为私有

2) 您不需要重写
GetHashCode()
以与
Equals
保持一致(或者它只是没有显示在您的代码摘录中)

3) 我建议实现
IEquatable
。您已经实现了
Equals(Rational)
,因此不需要添加任何其他方法

< P > 4)您的代码非常容易产生int溢出。考虑使用<代码> BigInteger <代码> s而不是<代码>长< /COD> S.


5) 除非你规范化你的有理数(分母>0并除以GCD),否则你会得到数学上等价的有理数,而这些有理数在比较时并不相等。

使你的
GCD
函数保持静态


它不使用任何实例成员,因为它是在设置实例成员之前调用的,所以它不能使用。

您需要调用默认构造函数才能使其工作:

public Rational(long num, long den) : this()
{
    // and here (GCD is underline) the 4. error
    long simple = GCD(num, den);
    this.Numerator = num;
    this.Denominator = den;
}
这里一个更大的问题是你有一个可变结构。这从来都不是一个好主意。我会:

public long Numerator {get; private set;}

谢谢你,我把我作业中的UML附在我的问题上。所以我必须这样写…但是谢谢你的提示:)是的,但这是我第一次在这里讨论可变结构:)如果我从属性中删除setter,我会遇到这个问题:属性或索引'Rational…'不能被分配到-,它是只读的,由UML,我必须删除setter。但如果我将其设置为私有(setter),它将是好的:)只需搜索可变结构,您将在该问题上找到很多。简短的版本是,可变结构在某些情况下具有奇怪的语义,这是我们宁愿避免的。具有公共setter的属性并没有那么糟糕,但有任何变化