0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WinFormsでジェネリッククラスのFormを継承してフォームデザイナーが利用できない?

0
Last updated at Posted at 2026-05-14

絶対的な結論

フォームをジェネリッククラスにすることはやめた方がいい。
理由は下記の通り。

  • フォームにリソースファイルがあるとビルドエラーになる。
  • .NET8+ の環境だと Form1 すらフォームデザイナーを開けなくなる。

開発時の環境に制約が出たり煩わしくなるのと、.NET移行が確実に悪くなるから、やっぱりやらない方が吉っぽいです。

当初の調べた結果

.NET Framework 4.8.1 WinFormsで、ジェネリックの型が確定しているフォームなら、リビルドすればフォームデザイナーで開くことができた。
圧倒的にフォームデザイナーで開くことができないのは、ジェネリックの引数が確定していないフォームを開こうとしたときである。

リビルドすればいいんじゃね?
なんでできないっていう結論付けられたんだっけ???

経緯

プログラムを作っていて、確かそういうことできないよなあーと思って試しに書いたら出来ちゃったんですよ。
あれ?って思って調べたら、やっぱり下記のような情報が出てきて、回避策も昔から言われている方法。
そして私もその認識だった。

でも出来ちゃったから検証してみた。
ここで紹介されている InheritForm 自体も、結局リビルドしないと開けないし、あれ?ってなった。

Visual Studio 2022 からできるようになったのかと思ったけど、2017, 2019 でも出来たんだよねー。
できないシーンが分からなくなっちゃった。

検証したコード

Form1.cs
using System.Windows.Forms;

namespace GenericFormTest
{
    public partial class Form1<T> : Form where T : class, new()
    {
        public T Hoge { get; }

        public Form1()
        {
            InitializeComponent();

            Hoge = new T();
        }
    }
}
Form2.cs
using System.Windows.Forms;

namespace GenericFormTest
{
    public class Form2<T> : Form1<T> where T : class, new()
    {
        public Form2()
        {
            
        }
    }
}
Form3.cs
namespace GenericFormTest
{
    public partial class Form3 : Form2<Class1>
    {
        public Form3()
        {
            InitializeComponent();
        }
    }
}
Class1.cs
namespace GenericFormTest
{
    public class Class1
    {

    }
}

コードの結果

Form1、Form3 は、通常のフォーム作成によってDesignerファイルも用意されているが、
Form2 に関しては、名前こそ Form2 だけど、クラス作成で用意していて、Designerファイルはない。

理由は、リビルドしたときにフォームデザイナーで表示できるかどうかが異なるから。

クラス フォームデザイナー
Form1 表示できる
Form2 表示できない
Form3 表示できる

そのため、Form2 はDesignerファイルを持つ必要がなくて、あくまで Form2 では、ジェネリックの引数について更なる制御をするためだけに留める形になる。
ダブルクリックするとフォームデザイナーが開かれちゃうから、そこはトレードオフかな。
だから、Form2 が下記のようなコードになっても全然通用する。

Form2.cs
namespace GenericFormTest
{
    public class Form2<T1, T2> : Form1<T1> where T1 : class, new() where T2 : class, new()
    {
        public T2 Fuga { get; }

        public Form2()
        {
            Fuga = new T2();
        }
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?