2

我正在尝试制作代表四维向量的结构。

我做了这样的事情:

struct Vector4D<T> 
{
    public T v1;
    public T v2;
    public T v3;
    public T v4;

    //...

    public static Vector4D<T> operator *(Vector4D<T> a, T b)
    {
        a.v1 *= b;
        a.v2 *= b;
        a.v3 *= b;
        a.v4 *= b;
        return a;
    }
}

好吧,如果 T 不是任何数字类型,如 Int32、Int64、Double、Single、Decimal 等,那么这个结构就没有意义了……

所以,我的问题是如何将 T 限制为以下类型之一:Int16、Int32、Int64、UInt16、UInt32、UInt64、Byte、SByte、Single、Double、Decimal?

我试图做这样的事情

struct Vector4D<T> where T : Int16, Int32, Int64 // and so go on
{
    //....
}

但它没有用。

4

2 回答 2

1

您必须为每种类型显式编写乘法方法。

但是,您可以稍微简化一下,因为这个可编译的代码示例显示:

using System;

namespace Demo
{
    internal class Program
    {
        static void Main()
        {
            var d = new Vector4D<double>{v1=1, v2=2, v3=3, v4=4};
            Console.WriteLine(d*2); // Prints 2, 4, 6, 8

            var i = new Vector4D<int>{v1=1, v2=2, v3=3, v4=4};
            Console.WriteLine(i*2); // Prints 2, 4, 6, 8

            // This will throw a "NotSupported" exception:
            var s = new Vector4D<string>{v1="1", v2="2", v3="3", v4="4"};
            Console.WriteLine(s*"");
        }
    }

    partial struct Vector4D<T>
    {
        public T v1;
        public T v2;
        public T v3;
        public T v4;

        public static Vector4D<T> operator *(Vector4D<T> a, T b)
        {
            a.v1 = multiply(a.v1, b);
            a.v2 = multiply(a.v2, b);
            a.v3 = multiply(a.v3, b);
            a.v4 = multiply(a.v4, b);
            return a;
        }

        public override string ToString()
        {
            return string.Format("v1: {0}, v2: {1}, v3: {2}, v4: {3}", v1, v2, v3, v4);
        }

        private static Func<T, T, T> multiply;
    }

    // Partial just to keep this logic separate.

    partial struct Vector4D<T>
    {
        static Vector4D() // Called only once for each T.
        {
            if (typeof(T) == typeof(int))
                Vector4D<int>.multiply = (a, b) => a*b;
            else if (typeof(T) == typeof(double))
                Vector4D<double>.multiply = (a, b) => a*b;
            else if (typeof(T) == typeof(float))
                Vector4D<float>.multiply = (a, b) => a*b;
            else
                multiply = (a, b) =>
                {
                    string message = string.Format("Vector4D<{0}> not supported.", typeof(T));
                    throw new NotSupportedException(message);
                };
        }
    }
}

这样,您可以将所有乘法(可能还有除法、加法和减法)逻辑放入第二个部分结构中,并将其与主逻辑分开。

第二个部分结构仅包含一个静态类型构造函数,对于用于创建结构的每个类型 T 仅调用一次(每个程序集域)。

您确实有查询类型的开销,但每次运行程序只有一次,我猜开销会非常低。

此外,您根本不必使用部分结构 - 您可以将静态类型构造函数与结构实现的其余部分放在一起。我只是将它作为示例分开,因为它是纯粹的初始化逻辑,您可以将其与结构的其余逻辑分开考虑。

重要请注意,如果您将 Vector4D 与尚未定义乘法运算的类型一起使用,您将NotSupportedExceptionstatic Vector4D(). 这至少可以准确地告诉您出了什么问题,大致如下:

Unhandled Exception: System.NotSupportedException: Vector4D<System.String> not supported.

于 2013-05-05T12:59:38.217 回答
0

你不能这样做,不能这样。

C# 对泛型类型一无所知T。是数字吗?它是一个字符串吗?你能用它做数学吗?

如果你想让这个工作,你必须使用通用计算器。您必须自己构建它。有关更多信息,请查看: http: //www.codeproject.com/Articles/8531/Using-generics-for-calculations

一个更简单的解决方案可能是:

a.v1 = Convert.ChangeType(Convert.ToDecimal(a.v1) * Convert.ToDecimal(b), typeof(T));

编辑

我在另一个位置创建了一些库函数。您可以使用它在您自己的代码中实现。用这些数字计算会很容易。您的 Vector 类将是:

partial struct Vector4D<T>
where T: IComparable<T>, IEquatable<T>
{
    public Number<T> v1;
    public Number<T> v2;
    public Number<T> v3;
    public Number<T> v4;

    public static Vector4D<T> operator *(Vector4D<T> a, T b)
    {
        a.v1 *= b;
        a.v2 *= b;
        a.v3 *= b;
        a.v4 *= b;
        return a;
    }
}

请参阅:https ://codereview.stackexchange.com/questions/26022/improvement-requested-for-generic-calculator-and-generic-number

于 2013-05-05T11:53:45.447 回答