6

C# で、プリミティブ型に基づいた型を持ち、それを複製して代わりに他のプリミティブを使用する方法があるのだろうか。

あまり明確ではないことはわかっています。これを説明する方法がよくわかりません (そして、英語は私の母国語ではありません。申し訳ありません...)。

簡単な例:

public struct Vector2d {
    public double X;
    public double Y;

    //Arithmetic methods: Length, normalize, rotate, operators overloads, etc...
}

問題は、この型の float と int32 バージョンが欲しいということです。

私が実際にやっていること(有効なC#コード):

//This type contains all useful methods
public struct Vector2d {
    public float X;
    public float Y;

    public Vector2f AsFloat() {
        return new Vector2f((float)X, (float)Y);
    }
    public Vector2f AsInteger() {
        return new Vector2i((int)X, (int)Y);
    }

    //Arithmetic methods
}

//These types are only here to be casted from/to, all the arithmetics methods are on the double-based type
public struct Vector2f {
    public float X;
    public float Y;

    public Vector2f AsDouble() {
        return new Vector2d(X, Y);
    }
    public Vector2f AsInteger() {
        return new Vector2i((int)X, (int)Y);
    }
}
public struct Vector2i {
    public int X;
    public int Y;

    public Vector2f AsFloat() {
        return new Vector2f(X, Y);
    }
    public Vector2f AsDouble() {
        return new Vector2d(X, Y);
    }
}

機能しますが、「セクシー」ではなく、AsXXX メソッドを使用して大規模なキャストを行う場合、パフォーマンスに影響が生じることは避けられません。

理想的には、3 つのタイプすべてに算術メソッドを使用することですが、維持するのは面倒です...

理想的な解決策は何ですか(疑似コード、有効なC#ではありません):

public struct Vector2<T> where T : numeric {
    public T X;
    public T Y;

    public T Length {
        return (T)Math.Sqrt(X * X + Y * Y);
    }
    //Other arithmetic methods
}

現時点ではこれが C# では不可能であることはわかっていますが、本当の質問は次のとおりです。

これを適切かつ効率的に処理する方法について何か考えはありますか?

私が考えてきたこと(疑似コード、有効なC#ではありません):

//The TYPE defined constant should be used by Vector2Body instead of plain typed "double", "float", etc...

public struct Vector2d {
    #define TYPE double
    #import Vector2Body
}

public struct Vector2f {
    #define TYPE float
    #import Vector2Body
}

public struct Vector2i {
    #define TYPE int
    #import Vector2Body
}

そうすれば、コードが重複せず、保守が容易になります

あなたのアイデアを待っています:)

PS:モデレーターが私の質問をより適切にフォーマットする方法についてアイデアを持っている場合は、自由に編集してください:)

4

3 に答える 3

4

次のようなことができます。

public struct Vector2<T> where T : IConvertible
{
    private readonly double x;
    private readonly double y;

    public Vector2(T x, T y)
    {
        this.x = x.ToDouble(CultureInfo.CurrentCulture);
        this.y = y.ToDouble(CultureInfo.CurrentCulture);
    }

    public T X
    {
        get
        {
            return ConvertBack(this.x);
        }
    }

    public T Y
    {
        get
        {
            return ConvertBack(this.y);
        }
    }

    private static T ConvertBack(double d)
    {
        return (t)Convert.ChangeType(d, typeof(T), CultureInfo.CurrentCulture); 
    }
}

ただし、ジェネリック治療を希望しない場合。次に、いくつかの特殊Vector2なタイプを使用することもできます。

于 2013-06-10T09:57:26.707 に答える
0

Jodrellが提案したのと同じ解決策について考えました。追加したいだけです:

private Vector2(double x, double y)
{
 this.x = x;
 this.y = y;
}

public Vector2<E> ToVector<E>() where E : IConvertible
{
 return  new Vector2<E>(x, y);
}
于 2013-06-10T13:59:52.677 に答える