質問するログイン新規登録

Q&A

解決済

3回答

3839閲覧

インターフェースに演算子をオーバーロードする方法

Iwancof

総合スコア9

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2018/08/15 05:40

0

0

前提・実現したいこと

C#でinterfaceに演算子のオーバーロードをしたい。

発生している問題・エラーメッセージ

インターフェースに演算子を含めることができません。

該当のソースコード

C#

1interface ITest { 2 public static double operator + (ITest A,ITest B); 3}

試したこと

実際にこのインターフェースを使用するクラスに演算子のオーバーロードを実装しようとしたが、設計上無理があったため、断念。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

Zuishin

2018/08/15 05:43

何が聞きたいのでしょう?
Iwancof

2018/08/15 05:47

インターフェースに演算子をオーバーロードして、そのインターフェースを含むインスタンスすべてにその演算ができるようにしたいです。あまり触っていない言語なので、不備があったらすみません。
Zuishin

2018/08/15 05:50

演算子のオーバーロードには実装が必要なのでインターフェースではできません。断念したのではないのですか?
Iwancof

2018/08/15 05:57

日本が苦手ですみません。断念したのは「このインターフェースを使うクラスに演算子をオーバーロードをすること」です。僕がやりたいのは、このインターフェースを持つすべての演算子に"+"の演算ができることを保証したいのですが、それがインターフェースにできないということは保証できないということですか?
guest

回答3

0

何でできなんだ…と疑問に思ったのでちょっと調べてみました。

演算子を再定義出来る言語は意外と少ないです。C++、C#、Scala、Kotlin、Python、Ruby、Perl6、Haskell、Swift、Rust、あれ、以外とあるっぽい。ただ、これらの言語を大きく分けると、演算子が関数としてオーバーロードしている言語と、演算子がただのインスタンスメソッドにすぎない言語に大別されます。

a + bという表現を解釈するとき、+(a, b)となるかa.+(b)となるかはかなりの違いがあります。C++はその柔軟性を生かすために、両方の解釈が出来るようにしました。**これが混乱の元です。**オブジェクト指向としてはa.+(b)とインスタンスメソッドとして解釈する方が正しく思えます。しかし、+(a, b)と解釈できる仕様は、オープンクラスではないC++のような言語において、既存の型を前置、ユーザー定義型を後置に取る演算子の動作を追加するために必要です。この+(a, b)解釈が出来ない言語では、例えばScalaは暗黙の型変換という仕組み、Rubyはcoerceというメソッドを介するという仕組み、といった別手段を用いないといけません。そう、a.+(b)という解釈だけでは無理が生じるので、C++では+(a, b)の両方が出来るようになったのです。

C#はC++からの簡素化を目指しました。演算子オーバーロードについても簡素化し、C++のような二つも書き方があるようなものは避けたかったのです。で、どうしたかというと、+(a, b)を取りました。この書き方は、インスタンスメソッドではありませんのでインスタンスに紐付けらる物ではありません。つまり、C++のように関数として書くか、C#のようにクラスメソッド(staticメソッド)として書く必要があると言うことです。

後は簡単です。インターフェースはインスタンスの動きの枠組みを決めるためのものであって、クラスそのものの枠組みを決めるための物ではありません。だからstaticメソッドは対象外になる、ただそれだけです。

なお、単なるメソッドであるScalaやRubyでは演算子の再定義は(必要であれば)積極的に使われているようにみえます。これらの言語は、書き方の違いだけで、他のメソッドと違いは無いからだと思います。


【おまけ】
Stack Overflowに何が何でも強制させたいという手法が載っていました。ただし、抽象クラスに限ります。
interface - Is there any way in C# to enforce operator overloading in derived classes? - Stack Overflow

C#

1public abstract class MyClass 2{ 3 public static MyClass operator +(MyClass c1, MyClass c2) 4 { 5 return c1.__DoAddition(c2); 6 } 7 8 protected abstract MyClass __DoAddition(MyClass c2); 9}

投稿2018/08/15 13:12

raccy

総合スコア21866

Zuishin

2020/04/10 01:37 編集

目的とは違いますが、ためになる回答なので高評価しました。
guest

0

このインターフェースを持つすべての演算子に"+"の演算ができることを保証したい

「すべての演算子クラスに」ということでしょうか?
演算子の定義を強制させるのではなく、既定の実装のようなものが欲しいという意味ですね?

C#14の拡張メンバー(演算子)はどうでしょうか。
C# 14 の新機能 | Microsoft Learn

TestATestBを足せるのか不明なため両方を用意しました。

cs

1Console.WriteLine(new TestA(1) + new TestA(2)); 2Console.WriteLine(new TestB(3) + new TestB(4)); 3Console.WriteLine(new TestA(1) + new TestB(4)); 4Console.WriteLine(new TestB(4) + new TestA(1)); 5 6Console.WriteLine(new TestC(1) + new TestC(2)); 7Console.WriteLine(new TestD(3) + new TestD(4)); 8// 演算子 '+' を 'TestC' と 'TestD' 型のオペランドに適用することはできません 9//Console.WriteLine(new TestC(1) + new TestD(4)); 10//Console.WriteLine(new TestD(4) + new TestC(1)); 11 12interface ITest 13{ 14 double Value { get; } 15} 16record TestA(double Value) : ITest; 17record TestB(double Value) : ITest; 18 19interface ITest<T> where T : ITest<T> 20{ 21 double Value { get; } 22} 23record TestC(double Value) : ITest<TestC>; 24record TestD(double Value) : ITest<TestD>; 25 26static class ITestExtensions 27{ 28 extension(ITest) 29 { 30 public static double operator +(ITest A, ITest B) => A.Value + B.Value; 31 } 32 extension<T>(ITest<T>) where T : ITest<T> 33 { 34 public static double operator +(ITest<T> C, ITest<T> D) => C.Value + D.Value; 35 } 36}

+演算子の定義を強制させたいのであれば、IAdditionOperatorsがあります。
IAdditionOperators<TSelf,TOther,TResult> インターフェイス (System.Numerics) | Microsoft Learn

投稿2026/07/21 15:50

TN8001

総合スコア10336

0

ベストアンサー

演算子のオーバーロードは、優秀なフレームワーク、ライブラリ製作者以外は必要のない機能のなので、
考えるだけ無駄だと思います。

普通に、.Add() でやったほうがいいと思います。

そもそも、複数のインタフェースがあったとき、それぞれのインタフェースで演算子をオーバーロードしたら、何が起こるかわからないものになると思います。

投稿2018/08/15 05:53

kiichi54321

総合スコア1986

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.25%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問