Rational Number struct的缺省值

InB*_*een 10 c# struct

我正在研究一个简单的数学库用于教育目的,我已经实现了一个struct代表Rational Number的数学库.显示结构核心字段的非常基本的代码是:

public struct RationalNumber
{
    private readonly long numerator;
    private readonly long denominator;
    private bool isDefinitelyCoprime;
    private static RationalNumber zero = 0;

    public RationalNumber(long numerator, long denominator)
    {
        this.numerator = numerator;
        this.denominator = denominator;
        this.isDefinitelyCoprime = false;
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

目前我正在实现一个RationalMatrix,你可能已经猜到,它将由RationalNumber类型元素组成.

我正在创建静态构建器的有用矩阵是Identity矩阵.代码如下:

public static RationalMatrix GetIdentityMatrix(int dimension)
{
    RationalNumber[,] values = new RationalNumber[dimension, dimension];

    for (int i = 0; i < dimension; i++)
       values[i, i] = 1;

    return new RationalMatrix(values);
}
Run Code Online (Sandbox Code Playgroud)

问题是这不起作用,因为my的默认值RationalNumber不是,0/1但是0/0这是一种特殊的值(Indeterminate form).

显然,一个解决方案很简单,只需将方法更改为:

public static RationalMatrix GetIdentityMatrix(int dimension)
{
    RationalNumber[,] values = new RationalNumber[dimension, dimension];

    for (int i = 0; i < dimension; i++)
       for (int j = i+1 ; j < dimension; j++)
       {
           values[i, i] = 1;
           values[i, j] = RationalNumber.Zero;
           values[j, i] = RationalNumber.Zero;
       }

       return new RationalMatrix(values);
}
Run Code Online (Sandbox Code Playgroud)

但这在某种程度上似乎是浪费精力,因为我基本上是将整个数组的值初始化两次.我认为以某种方式使默认值RationalNumber相等会更优雅0/1.如果RationalNumber是a class,那么这很容易做到,但是当它是a时,我想不出办法struct.我错过了一些明显的东西,或者没有办法避免 0/0作为我的默认值?

我想指出的是,我并不关心代码性能(如果这是我的瓶颈,那么我已经远远超过了我的目标).我只是想知道是否有一些构造(我不知道)允许你在一个中强加任意默认值struct.

编辑:错别字

编辑2:扩大问题范围

好吧,struct根据我有限的C#知识,似乎没有办法从我得到的输入和我自己的结论中强加任意默认值.

有人能给我一个线索,为什么结构必须这样做?是出于某种原因还是以这种方式实现,因为没有人想过指定定义默认值的选项?

And*_*ren 5

如果您不必区分不确定的0/0和其他0/N值,则可以将所有0/N视为零.也就是说,所有零都是有意义的(0/2等于0/1),并且所有除以零都是相等的,因此1/0 == 2/0.

public struct RationalNumber : IEquatable<RationalNumber>
{
    private readonly long numerator;
    private readonly long denominator;

    public RationalNumber(long numerator, long denominator)
    {
        this.numerator = numerator;
        this.denominator = denominator;
    }

    public bool IsZero 
    { 
       get { return numerator == 0; }
    }

    public bool IsInvalid 
    { 
       get { return denominator == 0 && numerator != 0; }
    }

    public bool Equals(RationalNumber r)
    {
       if (r.IsZero && IsZero)
         return true;
       if (r.IsInvalid && IsInvalid)
         return true;
       return denominator == r.denominator && numerator == r.numerator;
    }

    public bool Equals(object o)
    {
       if (!(o is RationalNumber))
         return false;
       return Equals((RationalNumber)o);
    }

    public int GetHashCode()
    {
       if (IsZero) 
         return 0;
       if (IsInvalid)
         return Int32.MinValue;
       return ((float)numerator/denominator).GetHashCode();
    }
}   
Run Code Online (Sandbox Code Playgroud)


Ben*_*Ben 0

最好为该结构提供一个默认构造函数:

public RationalNumber()
{
    this.numerator = 0;
    this.denominator = 1;
    this.isDefinitelyCoprime = false;
}
Run Code Online (Sandbox Code Playgroud)

然而这是不允许的。您也不能拥有实例初始化程序。

答案很简单,您必须接受内部字段必须初始化为零,但这并不意味着行为必须遵循。

    public struct Rational
    {
        private int _numerator;
        private int _denominator;
        public Rational(int numerator, int denominator)
        {
            // Check denominator is positive.
            if(denominator < 0){
                  denominator *= -1; 
                  numerator *= -1;
            }
            _numerator = numerator;
            _denominator = denominator== 0? -1:
                denominator;
        }
        public int Numerator
        {
            get { return _numerator; }
        }
        public int Denominator
        {
            get { return 
                _denominator == 0?1:
                _denominator == -1?0:
                _denominator; }
        }
    }
Run Code Online (Sandbox Code Playgroud)

(注意:我实际上非常惊讶地发现结构中不能有静态初始化器!)

  • 从什么时候开始允许这样做? (3认同)
  • -1 那是行不通的。创建 `RationalNumber` 数组不会调用此构造函数,因此不允许:*“结构不能包含显式无参数构造函数”* (2认同)
  • Ben,你的第二个建议也不起作用:*“结构中不能有实例字段初始值设定项”*。除了你的答案之外没有其他答案是有原因的:这是不可能的。 (2认同)