4


0

私はC#(.NET 2.0)で単純な抽象ジェネリッククラスを書きましたが、それを参照型のみに限定したいので、nullで値を示さないことができます。 しかし、私はまたlongやdecimalのような型を使いたいのです。なぜならnullを許さない(結局構造体である)のです。 私はクラスを作ることを考えました

パブリック抽象フィールド> {

}

しかし、それは私がクラスである文字列型を使用することを妨げるでしょう。 この総称でそれらを使用できるように、どのようにして小数点以下の桁数をボックス化することができますか。

抽象クラスField {private int _Length = 1;} private bool _Required = false;保護されたT _Value。 // = null。

public int Length {get {return _Length;}プライベートセット{if(value <1)は新しいArgumentExceptionをスローします( "フィールド長は少なくとも1でなければなりません")。 _Length =値。 }}

public bool必須{get {return _Required;}プライベートセット{_Required = value;} }}

パブリック抽象文字列GetFieldValue(); public abstract void ParseFieldValue(string s);

パブリック仮想T値{get {return _Value;} set {if(value == null)

}

0とnullの数値を別々に表す必要があることに注意してください。 このため、デフォルト(T)は機能しません。

6 Answer


3


(とりわけ)ジェネリック医薬品の大きなポイントはボクシングを避けることです。 thisを参照してください。

private bool _Required = false;
protected T _Value = default(T);

「0」と「未設定」を区別する必要がある場合は、 `+ object +`が唯一の方法です。

protected object _Value;

そしてbox-unbox-box-unbox。


2


2つのクラスが必要です

抽象クラスFieldRここで、T:class {T Value {get {} set {}}}

抽象クラスFieldVここで、T:struct {Nullable Value {get {} set {}}}

最初のクラスは使うでしょう

T

2番目のクラスは使うでしょうが

NULL可能


1


コンパイル時にジェネリックパラメータを適切に制限できるかどうかはわかりませんが、実行時のチェックを追加して、参照可能な型とNULL値の型のサブセットのみを許可することができます。

public virtual T Value
{
    get { return _Value; }
    set
    {
        Type t = typeof(T);
        if (t.IsValueType)
        {
            if (t.IsGenericType
                && (t.GetGenericTypeDefinition() == typeof(Nullable<>)))
            {
                Type u = Nullable.GetUnderlyingType(t);
                if ((u != typeof(long)) && (u != typeof(decimal)))
                {
                    throw new ArgumentException(
                        "Only long? and decimal? permitted!");
                }
            }
            else
            {
                throw new ArgumentException("Only nullable types permitted!");
            }
        }

        if ((value == null) && Required)
        {
            throw new ArgumentException("Required values cannot be null!");
        }

        _Value = value;
    }
}

(実際には、型チェックを `+ Value +`セッターではなくコンストラクターに入れたいと思うでしょう。)


0


これを試して:

public abstract Field
    where T : class
{

}

これはジェネリック型パラメータを参照型に制限します。 これは、このメソッドから「+ null」を返すことができる唯一の方法です。 はい、これはあなたがメソッドに値の型を渡すことを妨げるでしょう。


0


いい質問ですね。 私はこれが可能だったらいいのに:

class MyClassここでT:struct {T? 値; ... MyClassここで、T:class {Tの値。 ... }

そして、コンパイラーは、制約が満たされているかどうかに応じて正しい総称クラスを選択します。

残念ながら、それは機能しません、それは自動ソースコード生成に問題を引き起こす可能性があります。


0


T型のフィールドを公開する制約のない型パラメータTを使用して、クラスHolderを作成することをお勧めします。デフォルトのコンストラクタと、T型の単一引数コンストラクタの両方があります。 さらに、Holderによって実装されるIReadableHolderインターフェイスを定義することもできますが、定義する任意のクラス型によっても実装することができます(クラスFooのインスタンスは、そのValueプロパティを返すことでIReadableHolderを実装し、 IReadableHolderがHolderまたはfoo自体を受け入れることを期待しているルーチン。 残念ながら、IHolderの実装をStringクラスに追加するための「拡張インターフェース」を定義する方法はありません。