IFROAble あらため IMath
やはり、すでに人様の日記*1のコメントで書いているのですが、
interface IMathwhere T : IComparable, IFormattable, IConvertible, IComparable { T Add(left T, right T); }
などとしたとき、プリミティブ数値型はすべて上記インターフェスを実装しているので、IMath の実装クラス*2にはまったく変更なく実装が行われます。
しかし、IMath<T> を利用するクラスを作成するとき、
public class PrimitiveArraywhere T : IComparable, IFormattable, IConvertible, IComparable where I : IMath { }
などと制約を複製しないかぎりコンパイルエラーになります。この制約の複製はコンパイルエラーから簡単に判断できるので、書き忘れることも書くために調べ物をすることもないので我慢できる範囲ではあります。
しかし、前述したオーバーロード解決の問題で、IComparable と IComparable<T> のメソッドを解決するのがちょっと面倒です。
最初は IMath`1!0 の制約から IComparable を抜いて object 型で解決しようかとも思いましたが、数値型が対象であることを考えると、互換性のある型との親和性が微妙になりますが、ボックス化が発生する IComparable よりも IComparable
少し悩みましたが現在は、
// IMathでは制約を設けない public interface IMath where T : struct { ... } public struct MathUtils : IMath , IMath , ... { ... } // T.CompareTo() を利用したい実装を行う場合 public class PrimitiveArray where T : struct, IComparable where I : IMath { // このクラスの実装では CompareTo() できる }
と、制約を行うのは利用側に委ねる事にしました。
これが自然ですよね? ね?