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

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

ただいまの
回答率

90.76%

  • C#

    6562questions

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

ジェネリクスで変数を指定したい

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 175

Kyun001

score 11

 質問

ジェネリクスで変数を指定した場合以下のエラーが出ました。
ジェネリクスで変数を指定することは不可能なのでしょうか?

エラー    CS0118    'type' は 変数 ですが、種類 のように使用されています。

 エラーが出ないプログラム

class Program
{
    class MyClass1 { }
    class MyClass2 { }

    static void Deserialize<T>(byte[] data)
    {
        // デシリアライズ処理
        Console.WriteLine("Deserialize<T> is called");
    }

    static void Main(string[] args)
    {
        var data = new byte[] { 1, 2, 3 };

        // data の1バイト目で、
        // どのクラスとしてデシリアライズするかを別ける
        switch(data[0])
        {
            case 1:
                // data の1バイト目を飛ばす
                data = data.Skip(1).ToArray();
                Deserialize<MyClass1>(data);
                break;
            case 2:
                // data の1バイト目を飛ばす
                data = data.Skip(1).ToArray();
                Deserialize<MyClass2>(data);
                break;
        }
    }
}

 エラーが出るプログラム

class Program
{
    class MyClass1 { }
    class MyClass2 { }

    static void Deserialize<T>(byte[] data)
    {
        // デシリアライズ処理
        Console.WriteLine("Deserialize<T> is called");
    }

    static void Main(string[] args)
    {
        var data = new byte[] { 1, 2, 3 };

        var types = new Dictionary<int, Type>
        {
            [1] = typeof(MyClass1),
            [2] = typeof(MyClass2)
        };

        // data の1バイト目で、
        // どのクラスとしてデシリアライズするかを別ける
        var type = types[data[0]];
        // data の1バイト目を飛ばす
        data = data.Skip(1).ToArray();
        Deserialize<type>(data); // ここでエラーになる
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+3

できません。
求める結果を出す方法はいくつかありますが、Deserialize() を書き換えないなら次のようにします。

using System;
using System.Reflection;

namespace ConsoleApp1
{
    class Program
    {
        class MyClass1 { }

        static void Deserialize<T>(byte[] data)
        {
            foreach (var datum in data)
            {
                Console.WriteLine(datum);
            }
        }

        static void Main(string[] args)
        {
            var data = new byte[] { 1, 2, 3};
            var type = typeof(MyClass1);

            // (1) 問題ない
            //Deserialize<MyClass1>(data);

            // (2) エラー
            typeof(Program)
                .GetMethod(nameof(Deserialize), BindingFlags.Static | BindingFlags.NonPublic)
                .MakeGenericMethod(new[] { type })
                .Invoke(null, new[] { data });
            Console.ReadKey();
        }
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/01 10:38

    ありがとうございます。
    リフレクションを使うしかないのですね。

    キャンセル

  • 2018/05/01 10:41

    質問に書かれた情報からのみ判断するとそれが最適と思います。
    MyClass の型を変数 type に入れなければならないかどうかというところも検討してみてください。

    キャンセル

+3

こんにちは。

Deserialize<T>のシグニチャはどの型の場合でも同じなので、DictionaryにtypeではなくDeserialize<T>のデリゲートを登録して、それを呼び出せば近しいことができるだろうと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/01 11:54

    ありがとうございます、なるほどですね!
    試しに書いてみた所delegateで動きました。

    プログラム
    https://ideone.com/wAcqMS

    出力
    Deserialize<Test.Program+MyClass1> is called

    キャンセル

0

そりゃそこは変数を指定するところじゃないからです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

ジェネリクスに渡す型名は静的に決定されたものでなければいけないのでこれはできないです。

質問者さんがやりたいのはこういうことなのでは?

Type からインスタンスを生成する

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.76%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    C# xmlから配列に戻す

    <?xml version="1.0" encoding="UTF-8"?> <ArrayOfAnyType xmlns:xsd="http://www.w3.org/2001/X

  • 解決済

    C# ネットワーク間のシリアライズ

    今TCP/IPでクライアントとサーバーの通信をしています。 クライアントのClassをシリアライズし、サーバーに送りたいのですがやり方がイマイチわかりません。 クライアント

  • 解決済

    C#でHaskellとかにあるリスト分離

    C#で (x:xs) --Haskell 的なことってできないでしょうか? 手動で分離してタプルで返す拡張メソッド書けばいいかも知れませんが、 上記のようにシャッ!て分離

  • 解決済

    SNMPのOidを16進数にしてbyte配列に格納したい

    前提・実現したいこと C#でSNMPTrapをライブラリを使わずにパケットを直に 送信したいと考えています。 作成している最中にOidのパケット変換で躓いてしまったので質問をさ

  • 受付中

    【C#】配列の要素の削除についての質問です。

    配列の特定(null)のものを削除し、削除されたものを読みたい。 現在、データテーブルから持ってきたデータを配列の要素に代入しているのですが、 代入されていないnullの要素を削除

  • 解決済

    C#の動的キャストについて

    object型の値を持つDictionaryからKeyValuePairを一つずつ取り出しValueをbyte[]に変換する処理を作成しています。 イメージは以下になります。

  • 解決済

    Listで外部からアクセスできるインスタンスを作りたい

    List<T>をForm1で宣言し、Form2でListのインスタンスを作り値を入力・シリアル化します。 その後、Form3からXMLをロードしてForm2で作ったインスタンス(w

  • 解決済

    C# 間にスペースの入った標準入力の受け取りと利用

     前提・実現したいこと 10 100のような間にスペースの入った入力を、数値として10と100を別々に受け取ること or 何らかの方法による10と100を使った計算  試したこ

同じタグがついた質問を見る

  • C#

    6562questions

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