質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

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

Q&A

解決済

2回答

2665閲覧

あいまいなユーザー定義変換

Zuishin

総合スコア28660

C#

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

1グッド

1クリップ

投稿2016/06/23 05:34

編集2016/06/23 05:45

###前提・実現したいこと
下記のコードで「あいまいなユーザー定義変換」というコンパイルエラーが出ます。
もちろん、int から TestClass<int> へキャストするメソッドが二つあるために競合が起きるのは当然なのですが、この二つに優先順位をつけて、どちらか一方が呼び出されるようにはできないでしょうか?

###該当のソースコード

public static class Program { public static void Main() { Console.WriteLine((TestClass<int>)1); } } class TestClass<T> { public TestClass(int value) { } public static explicit operator TestClass<T>(int value) { return new TestClass<T>(value); } public static explicit operator TestClass<T>(T value) { return new TestClass<T>(1); } }

###試したこと
(TestClass<double>)1 のようにすれば、競合は起きませんが、優先順位をつける方法があれば知りたく思います。
どちらか、あるいは両方を implicit にしても意味がありませんでした。

###補足情報(言語/FW/ツール等のバージョンなど)
Visual C# 2013

###追記
2016/6/23
リフレクションを使えばインスタンス化自体はできますが、手軽にキャストでインスタンス化したく思います。

退会済みユーザー👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

確かwhere句で型ごとに条件分岐できるので,それで実装できないでしょうか。
また,それができなければ,typeofで型ごとに条件分岐ができるので,TestClass<T>(T value)メソッドに型ごとの条件分岐を入れるといいのではないでしょうか。

追記 ジェネリックパラメータを二つ使うと,メインのデータ構造の型と引数の型の不整合を防げます。
また,そのクラスを継承することで,型のデフォルト値を設定できます。

C#

1class TestClass<T>:TestClass<T,int> 2 { 3 4 } 5 6 class TestClass<T1,T2> 7 { 8 public TestClass(int value) { } 9 10 public static explicit operator TestClass<T1,T2> (T2 value) 11 { 12 if (typeof(T2) == typeof(int)) { 13 return new TestClass<T1,T2> (value); 14 } else if (typeof(T1) == typeof(T2)) { 15 return new TestClass<T1,T2> (1); 16 } else { 17 return new TestClass<T1,T2>(1); 18 } 19 } 20 }

ただ,ozwkさんもおっしゃっている通り,必要な機能に対して設計が良くないかもしれないので,参考までにお願いします。

投稿2016/06/23 06:46

編集2016/06/23 09:01
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2016/06/23 07:01

型制約はキャスト演算子に付けられませんし、 typeof云々は var x = (TestClass<Hoge>)1; // 1がHogeにキャストできないのでエラー になります。
Zuishin

2016/06/23 08:08

回答ありがとうございます。 型ごとに条件分岐はできないんじゃないでしょうか? 他に方法がなければコンストラクタ内で typeof で分岐するのが手っ取り早いかもしれませんね。 tkow さん、1 は Hoge にはキャストできませんが、TestClass<Hoge> にキャストすることは可能ですよ。 ただ、なぜキャストメソッドが二つ欲しいかというと、速度の問題なのです。速度が欲しい時には T を int にし、精度が欲しい時には decimal にしようと思っているのですが、内部分岐をするためにはコンストラクタを decimal にしなければなりません。 そうすると、結局内部でも decimal を扱わなければならなくなり、また型変換も多くなって思うように速度が出ないのです。
ozwk

2016/06/23 08:16

> 1 は Hoge にはキャストできませんが、TestClass<Hoge> にキャストすることは可能ですよ。 TestClass<T>(T value)だけを用意して、typeofで頑張ろうとすると (TestClass<Hoge>)1は、 TestClass<Hoge>.TestClass<Hoge>(Hoge value)を適用しようとして、 1を暗黙的にHogeに型変換しようとするのでエラーになる。 という意味です。
Zuishin

2016/06/23 08:17

失礼しました。おっしゃる通りです。
退会済みユーザー

退会済みユーザー

2016/06/23 08:48

なるほど思っていたより制約おおいですね。 どういうデータ構造や演算結果を求めてるかわからなかったので使えるかどうかわかりませんが,ジェネリックパラメータ2つにしても大丈夫なら型チェックできたので,コード載せておきます。 ただし,記述量が多くなるため,可読性が低下することと,速度面が向上するかどうかと,はわかりらないです。
Zuishin

2016/06/23 08:58

ありがとうございます。 「キャストで簡単に」というところがポイントで、要するに分数や複素数、その他新しい形の「数」を計算式の中で int や double などとシームレスに相互変換する基盤を研究していました。 コンパイラや電卓を作るうえでの基礎となるものですので、できればすっきりとした形にまとめたいのです。
Zuishin

2016/06/23 09:08

新しい回答拝見しました。 目からうろこが落ちる思いです。そんな書き方がるとは想像もしていませんでした。 一つ新しいアイデアをいただいたので、これを研究してみようと思います。
guest

0

コンストラクタで妥協しちゃいました
キャストで頑張れませんでした。

C#

1public class UnitTest1 2{ 3 [TestMethod] 4 public void TestMethod1() 5 { 6 var x = new TestClass<int>(1); // int 7 var y = new TestClass<double>(1); // int 8 var z = new TestClass<double>(1.0); // T 9 } 10} 11 12class TestClass<T> 13{ 14 public TestClass(int value) { Console.WriteLine("int"); } 15 public TestClass(T value) { Console.WriteLine("T"); } 16}

投稿2016/06/23 06:32

ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2016/06/23 08:10

回答ありがとうございます。やっぱりキャストは難しいのでしょうか。 なぜコンストラクタだとできるのにという疑問が残るんですが。 もう少し勉強します。
ozwk

2016/06/23 08:18

その言語で書きにくいことは そもそも(その言語的に)設計がおかしいと思うようにしたほうがいいかもしれませんね
Zuishin

2016/06/23 08:50

なるほどそうかもしれません。 設計の見直しも含めて考えているところですが、簡単な方法をどなたかご存知かと思ってお聞きしました。
Zuishin

2016/06/23 09:10

お時間とっていただいてありがとうございました。 いただいたアイデアは今後の糧にします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問