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

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

新規登録して質問してみよう
ただいま回答率
85.35%
.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

C#

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

Q&A

解決済

3回答

2142閲覧

C#でジェネリックが内包しているクラスのメソッドやプロパティを親に生やしたい

ST2020

総合スコア17

.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

C#

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

0グッド

0クリップ

投稿2020/06/09 02:58

編集2020/06/09 04:22

.NET CORE 3.1 C# 8.0

表題のイメージは以下のような形になります。
Tのメソッド、プロパティにショートカットで直接アクセスできる方法はないかと調べておりました。
※_dataをpublicにしてアクセスすればよいのですが、デリゲートのような形でアクセスを委任できるとスマートに書けるなと思いまして。

class Hoge<T> where T : class { T _data; public Hoge() { _data = new T(); } // 共通処理... } class A { public string A_Method(){ return "I am A." } public int A_Property { get; set; } } class B { public string B_Method(){ return "I am B." } public long B_Property1 { get; set; } public int B_Property2 { get; set; } } var hoge = new Hoge<A>(); hoge.A_Method(); hoge.A_Propaty; var hoge2 = new Hoge<B>(); hoge2.B_Method(); hoge2.B_Propaty1; hoge2.B_Propaty2;

良い方法がございましたらご教授いただけると助かります。

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

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

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

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

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

hihijiji

2020/06/09 03:17

根本的に何がやりたいのかを書いてください。 外からアクセスしたいなら公開すれば良いし、公開しないならアクセスされたらまずいわけですよね? それと_data = new T();と書いてますが、引数無しのコンストラクタを持たないクラスはどうしますか?
BluOxy

2020/06/09 03:40

hihijijiさんに同意します。 アクセスしたいだけであれば(A)hoge.A_Method();と書けば良いと思いますが、それだとジェネリッククラス経由でインスタンスを生成する必要性が分かりません。
ST2020

2020/06/09 03:43

情報が不足しており申し訳ございません。 やりたいことは外に公開はしたいけど、書き方を簡潔にしたいというところになります。 public T Data; hoge.Data.A_Propaty ↓ hoge.A_Propaty Tは引数無しのコンストラクタのクラスのみになります。 イメージではすいません省略していますが実際のwhereは細かく制約がつきます。
hihijiji

2020/06/09 03:54

Hoge<T> と T が継承関係にないのでできません。
ST2020

2020/06/09 04:00 編集

もう1点すいません。イメージでは省略しておりますが 実際のHogeクラスには各種共通の処理もはいります。 中のデータにアクセスしたい+共通処理のラッパークラスのようなジェネリッククラスとなります。
BluOxy

2020/06/09 04:25 編集

質問と関係があるかわかりませんが、AとBで共通点があり、Hogeクラスでそれらを使った共通の処理があるのであればAとBは継承なりinterfaceを実装するなりしてポリモーフィズムする方が良いかもしれません。適当なことを書いていたらスルーしてください。 ※そもそもHogeクラスが必要なのかどうかも分かりませんが…
ST2020

2020/06/09 04:29

おっしゃるとおりです。 Tに入る、AとBにinterfaceなり親クラスなりで書けるとよいのですが、外部のクラスのため構造は変更が難しい状態となっておりまして、今回のようなラッパー的なクラスを考えました。
BluOxy

2020/06/09 04:33 編集

質問文に var hoge = new Hoge<A>(); ではなく var hoge = new A(); ではいけない理由を記載して頂けるでしょうか。 おそらく「Hogeクラスには各種共通の処理もはいる」からだと思いますが、その共通の処理が何をしている(どうAとBに依存している)のかが分からないので、可能ならそれを無理のない形で質問のコードに追加して頂きたいです。
BluOxy

2020/06/09 04:35

改めて見直してみると、やりたいことが理解できました。
guest

回答3

0

おすすめはしません。

csharp

1using static System.Console; 2 3public class Program 4{ 5 static void Main() 6 { 7 var foo = new Foo<Bar>(new Bar()); 8 WriteLine(((dynamic)foo).Name); // "Bar" 9 } 10}

csharp

1using System; 2using System.Dynamic; 3using System.Reflection; 4 5class Foo<T> : DynamicObject 6{ 7 private Type innerType = typeof(T); 8 private T value; 9 10 public Foo(T value) 11 { 12 this.value = value; 13 } 14 15 public override bool TryGetMember(GetMemberBinder binder, out object? result) 16 { 17 PropertyInfo? pi = innerType.GetProperty(binder.Name); 18 if (pi != null) 19 { 20 result = pi.GetValue(value); 21 return true; 22 } 23 return base.TryGetMember(binder, out result); 24 } 25} 26class Bar 27{ 28 public string Name { get; } = "Bar"; 29}

投稿2020/06/09 05:30

編集2020/06/09 05:56
htsign

総合スコア870

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

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

ST2020

2020/06/09 07:14

まさにこのイメージでした!DynamicObjectのパフォーマンスも試してみたいと思います。 ありがとうございます。
guest

0

ベストアンサー

どうしてもhoge.A_Method();のような方法で呼び出したいのであれば、既存のオブジェクトから必要な情報を取り出して新しいオブジェクトを取り扱うのが良いと思います。下記コードの場合は新しいデータ保持用のオブジェクトを使って AModelA を has a 関係にしています。

public interface IModel{ int Property { get; set; } string Method(); } public class AModel: IModel{ private A a; public AModel(A a){ this.a = a; } public string Method(){ return a.A_Method(); } public int Property { get => a.A_Propaty; set => a.A_Propaty = value; } } public class BModel : IModel{ private B b; public BModel(B b){ this.b = b; } public string Method(){ return b.B_Method(); } public int Property { get => b.B_Propaty; set => b.B_Propaty = value; } public int B_Property2 { get => b.B_Propaty2 ; set => b.B_Propaty2 = value; } } public class Hoge { public void DoSomething(IModel model){ // 共通処理... Console.WriteLine($"Property is {model.Property}, Method is {model.Method()}"); } }

ジェネリックが内包しているクラスのメソッドやプロパティを親に生やしたい

上記コードのような対応の場合はジェネリックを使う必要がなくなります。

投稿2020/06/09 04:52

編集2020/06/09 05:05
BluOxy

総合スコア2663

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

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

BluOxy

2020/06/09 04:59 編集

しかし、よく考えればWrapperやジェネリッククラスを作る位ならもっと良い方法があると思います。 hoge.Data.A_Propaty→hoge.A_Propatyがしたいがために本来の目的から遠ざかっている印象です。 私ならAとBから必要な情報を抜き出したオブジェクトを生成して、それをHogeという共通処理を行うクラスに行わせるかもしれません。
BluOxy

2020/06/09 05:06

そう思ったので、回答を編集しました。ほとんどWrapperという名前をやめただけですが、そのアプリケーションで使う専用のデータオブジェクトという意味で、Modelに命名を変更しました。
ST2020

2020/06/09 06:01

色々とアドバイスありがとうございます。前提条件の漏れでわかりづらくてすいません。 AとBが別のシステムでも使用するサブモジュールとなっており、そちらを変更するができないため、今回のような変わった書き方となっておりました。 いただいた方法試してみたいと思います。
ST2020

2020/06/09 07:11

DynamicObjectが一覧イメージに近かったです。 ありがとうございます!
BluOxy

2020/06/09 11:00

参考になった方をBAに選ばれると良いと思います。 しかし、dynamicは存在しないプロパティにアクセスした場合に例外を吐く(つまり、動的型付けであるデメリットが発生する)ので、htsignさんの仰る通りおすすめはしません。
guest

0

_dataをpublicにするか、読み取り専用プロパティにするか、
でいいのでは

投稿2020/06/09 03:02

y_waiwai

総合スコア88042

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問