元ネタ:[C#]コンプレックスと戦う
C# ジェネリクスの制限に打ち勝つ
型制約として値型を用いることができない、operator+-*/ をGetMethod()できない、そんな C# ジェネリックでも、複素数型を定義してみました。
namespace Sample
{
using System;
using System.ComponentModel;
struct Complex<TValue>
{
public TValue Real { get; set; }
public TValue Imaginary { get; set; }
public static Complex<TValue> operator +(Complex<TValue> lft, Complex<TValue> rgt)
{
return new Complex<TValue>() { Real = Adder(lft.Real, rgt.Real), Imaginary = Adder(lft.Imaginary, rgt.Imaginary) };
}
public static Complex<TValue> operator -(Complex<TValue> lft, Complex<TValue> rgt)
{
return new Complex<TValue>() { Real = Subtractor(lft.Real, rgt.Real), Imaginary = Subtractor(lft.Imaginary, rgt.Imaginary) };
}
public static Complex<TValue> operator *(Complex<TValue> lft, Complex<TValue> rgt)
{
return new Complex<TValue>() { Real = Multiplier(lft.Real, rgt.Real), Imaginary = Multiplier(lft.Imaginary, rgt.Imaginary) };
}
public static Complex<TValue> operator /(Complex<TValue> lft, Complex<TValue> rgt)
{
return new Complex<TValue>() { Real = Divider(lft.Real, rgt.Real), Imaginary = Divider(lft.Imaginary, rgt.Imaginary) };
}
static Complex()
{
var tvalue_type = typeof(TValue);
if (tvalue_type == typeof(sbyte))
{
Complex<sbyte>.Adder = (x, y) => (sbyte)(x + y);
Complex<sbyte>.Subtractor = (x, y) => (sbyte)(x - y);
Complex<sbyte>.Multiplier = (x, y) => (sbyte)(x * y);
Complex<sbyte>.Divider = (x, y) => (sbyte)(x / y);
}
else if (tvalue_type == typeof(byte))
{
Complex<byte>.Adder = (x, y) => (byte)(x + y);
Complex<byte>.Subtractor = (x, y) => (byte)(x - y);
Complex<byte>.Multiplier = (x, y) => (byte)(x * y);
Complex<byte>.Divider = (x, y) => (byte)(x / y);
}
else if (tvalue_type == typeof(short))
{
Complex<short>.Adder = (x, y) => (short)(x + y);
Complex<short>.Subtractor = (x, y) => (short)(x - y);
Complex<short>.Multiplier = (x, y) => (short)(x * y);
Complex<short>.Divider = (x, y) => (short)(x / y);
}
else if (tvalue_type == typeof(ushort))
{
Complex<ushort>.Adder = (x, y) => (ushort)(x + y);
Complex<ushort>.Subtractor = (x, y) => (ushort)(x - y);
Complex<ushort>.Multiplier = (x, y) => (ushort)(x * y);
Complex<ushort>.Divider = (x, y) => (ushort)(x / y);
}
else if (tvalue_type == typeof(int))
{
Complex<int>.Adder = (x, y) => (int)(x + y);
Complex<int>.Subtractor = (x, y) => (int)(x - y);
Complex<int>.Multiplier = (x, y) => (int)(x * y);
Complex<int>.Divider = (x, y) => (int)(x / y);
}
else if (tvalue_type == typeof(uint))
{
Complex<uint>.Adder = (x, y) => (uint)(x + y);
Complex<uint>.Subtractor = (x, y) => (uint)(x - y);
Complex<uint>.Multiplier = (x, y) => (uint)(x * y);
Complex<uint>.Divider = (x, y) => (uint)(x / y);
}
else if (tvalue_type == typeof(long))
{
Complex<long>.Adder = (x, y) => (long)(x + y);
Complex<long>.Subtractor = (x, y) => (long)(x - y);
Complex<long>.Multiplier = (x, y) => (long)(x * y);
Complex<long>.Divider = (x, y) => (long)(x / y);
}
else if (tvalue_type == typeof(ulong))
{
Complex<ulong>.Adder = (x, y) => (ulong)(x + y);
Complex<ulong>.Subtractor = (x, y) => (ulong)(x - y);
Complex<ulong>.Multiplier = (x, y) => (ulong)(x * y);
Complex<ulong>.Divider = (x, y) => (ulong)(x / y);
}
else if (tvalue_type == typeof(float))
{
Complex<float>.Adder = (x, y) => (float)(x + y);
Complex<float>.Subtractor = (x, y) => (float)(x - y);
Complex<float>.Multiplier = (x, y) => (float)(x * y);
Complex<float>.Divider = (x, y) => (float)(x / y);
}
else if (tvalue_type == typeof(double))
{
Complex<double>.Adder = (x, y) => (double)(x + y);
Complex<double>.Subtractor = (x, y) => (double)(x - y);
Complex<double>.Multiplier = (x, y) => (double)(x * y);
Complex<double>.Divider = (x, y) => (double)(x / y);
}
else if (tvalue_type == typeof(decimal))
{
Complex<decimal>.Adder = (x, y) => (decimal)(x + y);
Complex<decimal>.Subtractor = (x, y) => (decimal)(x - y);
Complex<decimal>.Multiplier = (x, y) => (decimal)(x * y);
Complex<decimal>.Divider = (x, y) => (decimal)(x / y);
}
else
{
throw new NotSupportedException();
}
}
private static Func<TValue, TValue, TValue> Adder { get; set; }
private static Func<TValue, TValue, TValue> Subtractor { get; set; }
private static Func<TValue, TValue, TValue> Multiplier { get; set; }
private static Func<TValue, TValue, TValue> Divider { get; set; }
public override string ToString()
{
return String.Format("({0}) + ({1})i", Real.ToString(), Imaginary.ToString());
}
}
class Program
{
static void Main(string[] args)
{
#region +
Console.WriteLine((new Complex<sbyte> { Real = 1, Imaginary = 1 } + new Complex<sbyte> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<byte> { Real = 1, Imaginary = 1 } + new Complex<byte> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<short> { Real = 1, Imaginary = 1 } + new Complex<short> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<ushort> { Real = 1, Imaginary = 1 } + new Complex<ushort> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<int> { Real = 1, Imaginary = 1 } + new Complex<int> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<uint> { Real = 1, Imaginary = 1 } + new Complex<uint> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<long> { Real = 1, Imaginary = 1 } + new Complex<long> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<ulong> { Real = 1, Imaginary = 1 } + new Complex<ulong> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<float> { Real = 1, Imaginary = 1 } + new Complex<float> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<double> { Real = 1, Imaginary = 1 } + new Complex<double> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<decimal> { Real = 1, Imaginary = 1 } + new Complex<decimal> { Real = 1, Imaginary = 2 }).ToString());
#endregion
#region -
Console.WriteLine((new Complex<sbyte> { Real = 1, Imaginary = 1 } - new Complex<sbyte> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<byte> { Real = 1, Imaginary = 1 } - new Complex<byte> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<short> { Real = 1, Imaginary = 1 } - new Complex<short> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<ushort> { Real = 1, Imaginary = 1 } - new Complex<ushort> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<int> { Real = 1, Imaginary = 1 } - new Complex<int> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<uint> { Real = 1, Imaginary = 1 } - new Complex<uint> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<long> { Real = 1, Imaginary = 1 } - new Complex<long> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<ulong> { Real = 1, Imaginary = 1 } - new Complex<ulong> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<float> { Real = 1, Imaginary = 1 } - new Complex<float> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<double> { Real = 1, Imaginary = 1 } - new Complex<double> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<decimal> { Real = 1, Imaginary = 1 } - new Complex<decimal> { Real = 1, Imaginary = 2 }).ToString());
#endregion
#region *
Console.WriteLine((new Complex<sbyte> { Real = 1, Imaginary = 1 } * new Complex<sbyte> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<byte> { Real = 1, Imaginary = 1 } * new Complex<byte> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<short> { Real = 1, Imaginary = 1 } * new Complex<short> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<ushort> { Real = 1, Imaginary = 1 } * new Complex<ushort> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<int> { Real = 1, Imaginary = 1 } * new Complex<int> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<uint> { Real = 1, Imaginary = 1 } * new Complex<uint> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<long> { Real = 1, Imaginary = 1 } * new Complex<long> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<ulong> { Real = 1, Imaginary = 1 } * new Complex<ulong> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<float> { Real = 1, Imaginary = 1 } * new Complex<float> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<double> { Real = 1, Imaginary = 1 } * new Complex<double> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<decimal> { Real = 1, Imaginary = 1 } * new Complex<decimal> { Real = 1, Imaginary = 2 }).ToString());
#endregion
#region /
Console.WriteLine((new Complex<sbyte> { Real = 1, Imaginary = 1 } / new Complex<sbyte> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<byte> { Real = 1, Imaginary = 1 } / new Complex<byte> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<short> { Real = 1, Imaginary = 1 } / new Complex<short> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<ushort> { Real = 1, Imaginary = 1 } / new Complex<ushort> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<int> { Real = 1, Imaginary = 1 } / new Complex<int> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<uint> { Real = 1, Imaginary = 1 } / new Complex<uint> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<long> { Real = 1, Imaginary = 1 } / new Complex<long> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<ulong> { Real = 1, Imaginary = 1 } / new Complex<ulong> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<float> { Real = 1, Imaginary = 1 } / new Complex<float> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<double> { Real = 1, Imaginary = 1 } / new Complex<double> { Real = 1, Imaginary = 2 }).ToString());
Console.WriteLine((new Complex<decimal> { Real = 1, Imaginary = 1 } / new Complex<decimal> { Real = 1, Imaginary = 2 }).ToString());
#endregion
}
}
}
ちなみに、string でも Adder だけは定義可能なので、επιστημη氏の「あらあらあら」も C# で可能。