10

私は教育目的で単純な数学ライブラリに取り組んでおり、有理数structを表す aを実装しました。構造体のコア フィールドを示す非常に基本的なコードは次のとおりです。

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;
    }

    ...
}

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);
}

問題は、 my のデフォルト値がそうではなく、特別な種類の値 (不定形) であるため、これが機能しRationalNumberないことです0/10/0

明らかに、1 つの解決策は簡単で、単純にメソッドを次のように変更することです。

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);
}

しかし、基本的に配列全体の値を2回初期化しているため、これはどういうわけか無駄に思えます。どういうわけかデフォルト値をRationalNumberequalにする方がエレガントだと思います0/1。RationalNumber が の場合、これは簡単に実行classできますが、 の場合はそれを行う方法が思いつきませんstruct。明らかな何かが欠けて 0/0いますか、それともデフォルト値として持たないようにする方法はありませんか?

コードのパフォーマンスについてはまったく気にしていないことを指摘したいと思います (これがボトルネックになるとしたら、すでに目標をはるかに超えていることになります)。に任意のデフォルト値を課すことを可能にするいくつかの構造(私には知られていない)があるかどうか知りたいだけですstruct

編集:タイプミス

編集2:質問の範囲を広げる

structOK、私が取得している入力から、および私の限られたC#知識に基づく私自身の結論から、a に任意のデフォルト値を課す方法はないようです。

構造体がこのように動作しなければならない理由について、誰かが私に手がかりを与えることができますか? それは理由があるのでしょうか、それともデフォルト値を定義するオプションを指定することを誰も考えなかったためにこのように実装されたのでしょうか?

4

4 に答える 4

1

デフォルト値を割り当てるパラメーターなしのコンストラクターを使用することはできません。技術的な理由は、 yourstructが のサブクラスでありSystem.ValueType、 でSystem.ValueType()あるprotectedため、オーバーライドできないためです。

あなたが得ることができる最も近いものは、おそらくDavid Heffermanのソリューションです:

/// <summary>
/// The denominator is stored in this altered form, because all struct fields initialize to 0 - and we want newly created RationalNumbers to be 0/1 more often than 0/0.
/// </summary>
private int _denominatorMinusOne;
public int Denominator 
{ 
    get { return _denominatorMinusOne + 1; } 
    set { _denominatorMinusOne = value -1; } 
}

次に、コード内で通常どおり参照するだけDenominatorで、特別なストレージ形式が透過的になります。フィールド宣言を見るか、デフォルトのコンストラクターの動作を精査することによってのみ知ることができます。

パラメータを指定してコンストラクタを呼び出したり、RationalNumberFactoryゼロを生成するクラスを作成したりすることもできますが、コンストラクタを指定できないため、対角線だけでなく行列のすべての要素をループするという問題を回避することはできません。配列初期化子が使用するもの。

実際、このnew RationalNumber[100][100]規則は単なるコーディングの省略形ではなく、コンストラクターを 10,000 回呼び出すよりも高速に実行されます。これは、そもそもSystem.ValueType()が作成された理由の一部です。protected参照: .NET で構造体の既定のコンストラクターを定義できないのはなぜですか?

マトリックスのすべての要素をループすることは、明快さの点で利点がありますが、「奇妙な」マイナス 1 ソリューションを使用すると、実行する必要があるコードの量が減るだけでなく、パフォーマンスが向上します。したがって、これを支持する強力な議論と見なすことができます。

于 2014-02-25T19:32:43.260 に答える