• ベストアンサー

C#で実行時にメソッドの返り値の型を変化させる

C# で、実行時にメソッドの返り値の型を変化させることは可能でしょうか? たとえば、 public class MyData { object o; public void setValue( object a ) { o = a; } public object getValue() { return o; } } というクラスがあるとき、 static void Main(string[] args) { MyData a = new MyData(); a.setValue( 3 ); Console.WriteLine( a.getValue().GetType().ToString() ); int i = (int)a.getValue(); } というコードを実行すると、 System.Int32 と表示されます。Main の 4 行目で、(int)のキャストをはずすと、object から int への暗黙の変換はできませんというコンパイルエラーになります。 この(int)のキャストをしなくてもエラーにならないような getValue の関数はできないでしょうか? o は、数値型であるとします。 たとえば、MyData に、 public int getInt() { return (int)o; } とすれば、必ず int を返すようなメソッドはできると思うのですが、これだと、getByte() や、getDouble() などのように、考えられるすべての型を想定してメソッドを作ることになってしまいます。 そうではなく、getValue() で、少なくとも数値型の暗黙の変換はしてくれるようなことにできないでしょうか。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

#2です、少し補足します #2>int i = a.getValue(); #2>のようには書けなくて getValue()を 次のように書く場合(#2と同じ理屈)は、 public MyData getValue(){ return this; } … i = a.getValue(); と書けます

migoreng
質問者

お礼

確かにこれもできました。 戻り値の型を MyData としておくところがポイントなのですね。 補足ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (2)

  • UKY
  • ベストアンサー率50% (604/1207)
回答No.3

今度 11 月に出る C# の新バージョンでは Generics が使えるようになるので、とてもスマートな書き方ができるようになります。 public class MyData<T> { T o; public void setValue( T a ) { o = a; } public T getValue() { return o; } } のように書いておけば、 MyData<int> a = new MyData<int>(); a.setValue( 3 ); int i = a.getValue(); のように書けます。int でも double でも string でも何でも対応できます。

migoreng
質問者

お礼

そうなのですか。template みたいなものですね。 この場合、クラスのインスタンスを生成する時点で、そのクラスの T が決定しますよね。その後、同じクラスのインスタンスで T を変更することはできるのでしょうか。 どうもありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

このような場合、C#では、ユーザー定義の暗黙の変換を定義できます。 以下サンプル ------------------------------------------------------------------ using System; using System.IO; public class MyData{ object o; public void setValue( object a ){ o = a; } public object getValue(){ return o; } public static implicit operator int(MyData d) { return (int)d.o; } static void Main(string[] args){ MyData a = new MyData(); a.setValue( 3 ); Console.WriteLine( a.getValue().GetType().ToString() ); int i = a; Console.WriteLine(i); } } --------------------------------------------------------------- public static implicit operator int(MyData d) { return (int)d.o; } の部分が暗黙の変換を定義している部分 こうしておくと int i = a; の様に、要求される型に応じて暗黙に変換されます。 ただ、変換要求される型をあらかじめ定義しておかなけれならないのはしょうがないことです。 数値型については、そもそも上位型への暗黙の変換があるので、全てが必要になるというわけではないと思います。 ちなみに、object型についてはこうしたユーザー定義の暗黙の変換演算子を定義することができません。(既に定義されているから) なので、 int i = a.getValue(); のようには書けなくて int i = a; のようになります。 でもまあ、こうした暗黙の変換というのは、ソースを読む上ではわかりにくくなりますから明示的にキャストするのがよろしいかと存じます。

migoreng
質問者

お礼

早速試してみました。暗黙の変換が定義できるとは知りませんでした。 ご回答ありがとうございました。勉強したいと思います。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • C#の動的キャスト

    いつもお世話になっています。 C#の動的キャストに関する質問です。 C#のメソッドにobjectの引数を渡して動的にキャストする場合 void Hoge(object obj) { Type t = Type.GetType(obj); objの型 obj2 = (objの型)Convert.ChangeType(obj, t); //(1) ................................. } のようにされています。 しかし多様性をもつobjcetを引数にする多くの場合は「objの型」は不定です。 逆に言えば「objの型」がわかっている場合はわざわざobjectを引数にする必要はないわけです。 そこで質問ですが、何とかType t から「objの型」を取得して(1)記法による動的キャストを行う方法はないでしょうか? GetMethod, GetPropertyでメソッド,プロパティを取得し、Invoke, GetValue, SetValueすることは可能ですが、できればドット記法(.)が使える (1) のような動的キャストを行いたいと考えています。 よろしくお願いします。

  • 実行時に確定するメソッドを呼び出す方法について

    invoke()メソッドや、Methodクラスを 使用するなど。以前に小耳にはさんだ。記憶があります。 以下の3つの引数から 動的に該当メソッドを呼び出す。 処理を実装コードがすぐだせる方がいると 助かります。 Object foo(Object obj, String methodName, Collection param) (1)該当オブジェクト getClass()などで、該当クラスを動的に  特定。 (2)、(1)が保有しているメソッドのうち、 発行したいメソッドの名前 (3) parmには1要素ごとに2要素のObject[]型を   を格納して、 Object[0]の要素にかんしてはが引数の型についての完全修飾クラス名をあらわすString型。   Object[1]については実際に入っている値。 上記3つの引数をうけとって内部で getClass()とかつかって 必要な情報はすべて実行時に動的に 取得して objの該当オブジェクトを 発行し、foo()メソッド自体の 返却値はそのメソッドの返却値とする という ロジックの実装のサンプルがあると。 とても、うれしいです。 じゃ、void型が返却の時どうすんねん。 とか、staticの時どうすんねん。 とか、その変のアイデア持ってる 人がいるととてもうれしい。 以上

    • ベストアンサー
    • Java
  • c# Equalsメソッドについて

     こんにちは、c#初心者です。  以前まで「Object」型から継承される「Equals」メソッドをオーバーライドするときは public bool override Equals(object obj) {   if ( obj is 現在の型 または 任意の親クラスの型 や インターフェイスの型 )     {     //判断処理     }   else     return false; }  または、クラス限定で public bool override Equals(object obj) {   var temp = obj as 現在の型 または 任意の親クラスの型 や インターフェイスの型;   if ( temp != null )     {     //判断処理     }   else     return false; }  のようにしていたのですが、「is演算子なんて封印してしまえばいいのに」と仰る方がいらしたので、「is演算子を使わない方がよいのか?」と、「現在のメソッドの形式に不備はないのだろうか?」ということが気になり質問させていただきました。  is演算子を使わないとなると、もう「typeof演算子」を利用する事くらいしか思いつきません。  主に「is演算子」を使っているのは「Equals」メソッドなので、とりあえず「Equal」メソッドだけで。上記メソッドに不備、改善点があればご指摘願います。

  • C#で型変換がうまくいきません。

    C#で型変換がうまくいきません。 short r; byte[] b = new byte[] {1,2,3}; r = (short)b[1] * (short)256; というコードを書くと、 型 'int' を 'short' に暗黙的に変換できません。明示的な変換が存在します。(cast が不足していないかどうかを確認してください) と出てしまいます。キャストしているのに何がいけないのか全くわかりません。 どうぞ宜しくお願いいたします。

  • 出力結果が得られる理由が分かりません

    一つ目のプログラムソース: public class Array{ public static void main(String[] args){ int[] a={1,2,3,4}; int[] b={5,6,7,8}; System.out.print(a[2]); System.out.print(b[2]); b=a; System.out.print(a[2]); System.out.print(b[2]); b[2]=0; System.out.print(a[2]); System.out.print(b[2]); } } 出力結果:  373300 二つ目のプログラムソース: class Box{ private int value; public Box(){value=0;} public Box(int v){setValue(v);} public void setValue(int v){value=v;} public int getValue(){return value;} public Box copy(){ Box b=new Box(); b.setValue(getValue()); return b; } } public class BoxTest{ public static void main(String[] args){ Box x=new Box(1); Box y=new Box(2); Box z=new Box(3); x=z.copy(); y=z; System.out.print(x.getValue()); System.out.print(y.getValue()); System.out.println(z.getValue()); System.out.println(x==y); System.out.println(y==z); System.out.println(z==x); } } 出力結果:  333 false true false この二つのプログラムがどうしてこのような出力結果になるのかが分かりません。 良かったら教えてください。

    • ベストアンサー
    • Java
  • Javaのプログラムについて至急教えてください!

    //Sub.java class Super{ public void A(){} } class Sub extends Super{ /* (1) */ } このプログラムの(1)に入るものを下から2つ選んで他のクラスのメインメソッドから呼び出すのですがどうやってもわかりません。わかる方教えてください! public void A(){} public String A(){ return "pool";} public int A(String str){return Integer.parseInt(st);} public int A(){return 3;} public Object A(){return new Object();}

    • ベストアンサー
    • Java
  • c#のToString()メソッド

    http://msdn.microsoft.com/ja-jp/library/ms173154(v=vs.90).aspx のページによると C# では、すべてのオブジェクトが ToString メソッドを継承します。このメソッドは、該当するオブジェクトの文字列形式を返します。たとえば、int 型の変数はすべて ToString メソッドを持ち、次のようにその変数の内容を文字列として返すことができます ↑と書いてあるのですが、C言語しか知らない自分にとってint型の変数が関数、メソッドを持つ、 という概念が理解できません。これはオブジェクト指向の話なのでしょうか?クラスを理解すると わかるようになりますか? どなたかよろしくお願いします。

  • Java 可変長引数と優先度

    Java 可変長引数と優先度  こんにちは。c#初心者兼、java始めました です。  可変長引数の場合のオーバーロードの優先度について困っています(質問と言うより半分愚痴です)。  javaにも可変長引数ってありますよね。(ジェネリックの弱さにイライラしていたけれど)「javaも捨てたものじゃない」と感心しながら使っていると、いきなりコンパイルエラー。  sampleMethod(10, 20); と書いている部分でエラーが発生していました。  自分のメソッド定義を確認しみると、  void sampleMethod(int...);  void sampleMethod(Object...);  の2種類のオーバーロードがあり、ambiguousなため判別不能らしいです。    確かに、AutoBoxingされれば、int...だけでなく、Object...にもマッチしますが、どう考えてもBoxingしない方が優先度が高いはずです。というか、高く設定されるべきです。  個人的に基準にしているc#ではこのようなことは起きませんでした。  (あ、やっぱり捨てたものかもしれない ←心変わり早す(ry )    試しにc#でInteger型のクラスを作り、(実際はタブーですが)暗黙のキャストを双方向でオーバーロードして実験してみました。   public class Integer // ここからc# {   private int _value;   //----------------------------   public Integer(int value) { _value = value; }   //----------------------------   // Integer → int の暗黙の型変換   public static implicit operator int(Integer value)   { return value._value; }   // int → Integer の暗黙の型変換   public static implicit operator Integer(int value)   { return new Integer(value); }   //----------------------------   // javaの sampleMethod(int... values)に相当   public static void SampleMethod(params int[] values) { }   // javaの sampleMethod(Object... values)に相当   public static void SampleMethod(params Object[] values) { } }  そして、Integer.SampleMethod(10, 20); と書いてみると……問題……なし。  ちゃんと、SampleMethod(param int[] values)が選ばれていました。  つまり、(個人的には)java(コンパイラ)の方が不可解な動きをしているのです。  sampleMethod(int, int)とsampleMethod(Object, Object)があるときは問題ないので、可変長引数のときだけambiguousになるようです。  「それなら」と思い、sampleMethod(int, int...)とsampleMethod(Object, Object...)を作ってみましたが、やはりエラーが出ます。  何か良い解決策はあるでしょうか?  可変長じゃない引数のオーバーロードを大量に作ることと、片方の可変長をやめること以外でアドバイスをお願いします。  もしくは、「個人的には~だから、パクリのc#よりjavaの方が動きが正しいぞ!」という方がいらっしゃいましたら、ご意見ください。

  • フィールドを持たないクラスが、値を保持できる理由

    なぜint型フィールドを持たないMyGenericsクラスが変数やリテラルを保持できるのでしょうか? Objectクラスのフィールドを持っていますが、Objectクラスも、 フィールドは持っていませんよね?メソッドも空のObject()しか持っていないですし。 一応、javadocを読んだのですが、読み方間違えていますか? http://dlc-cdn.sun.com/jdk/jdk-api-localizations/jdk-api-ja/builds/latest/html/ja/api/index.html --------------------code-------------------------------- public class MyGenericsTest { public static void main(String[] args) { int x = 234; MyGenerics g = new MyGenerics(x); Integer i = (Integer)g.get(); System.out.println(i); } } class MyGenerics { Object o; public MyGenerics(Object o){ this.o = o; } public Object get(){ return o; } }

    • ベストアンサー
    • Java
  • C#でのDLLのメソッドの作り方

    MEFを使ってC#のプログラムを作っています。 DLL側のメソッドとして public bool ブーリアン(){     return true; } public string ストリングス(){ return "文字列"; } のような、戻り値をDLLからメインに送ることはできるのですが、 public void ナビ(int a){ webBrowser1.Navigate(http・・・・); Thread.Sleep(a); webBrowser1.Navigate(http・・・・); Thread.Sleep(a); }//webBrowser1はメインにある このような処理をDLLに入れようとすると、当たり前ですが「webBrowser1」なんてないぞ っと怒られてしまいます。 どのように渡せばよいのでしょうか?

TD-2130NSAについて
このQ&Aのポイント
  • TD-2130NSAはiPhoneでも使用できるのかについての相談です。Bluetoothの機械を購入すれば、iPhoneだけでラベルを作って印刷することができるか確認したいと思っています。
  • お使いの環境はiOSです。接続方法に関しては具体的な情報が提供されていません。
  • 関連するソフト・アプリや電話回線の種類についての情報も提供されていません。
回答を見る

専門家に質問してみよう