2016-11-19[土] C++TemplateのつもりでC#Generics使ってハマる(初歩)
人様のソース改修でロクに知らないC#をここ1,2ヶ月さわってた。 C++だと
#include <stdio.h> class Foo { public: void Run() { printf("Foo!"); } }; template<class T> class FooMgr { public: void Run() { T().Run(); } }; class Bar : public Foo { public: void Run() { printf("Bar!"); } }; class BarMgr : public FooMgr<Bar> { }; int main() { BarMgr barMgr; barMgr.Run(); } で "Bar!!" と出力されるようなつもりで
class Foo { public void Run() { System.Console.Write("Foo!"); } } class FooMgr<T> where T : Foo, new() { public void Run() { (new T()).Run(); } } class Bar : Foo { public new void Run() { System.Console.Write("Bar!!"); } } class BarMgr : FooMgr<Bar> { } class Test { public static void Main() { BarMgr barMgr = new BarMgr(); barMgr.Run(); } } のように書いてみたところ、実行したら "Foo!" が出力される、と。
初歩的な勘違いバグの類で、C# Generics って C++ Template ほど Macro的な強力さはなくて、この場合 継承class のラッパー的なモノでしかないのね。
where T : Foo で継承的な記述からとっとと気づけよなんだけど、ググって見よう見まね、要求を書いてるだけのつもりになってた。
class Foo { public virtual void Run() { System.Console.Write("Foo!"); } } class FooMgr<T> where T : Foo, new() { public void Run() { (new T()).Run(); } } class Bar : Foo { public override void Run() { System.Console.Write("Bar!!"); } } class BarMgr : FooMgr<Bar> { } class Test { public static void Main() { BarMgr barMgr = new BarMgr(); barMgr.Run(); } } どうせbase側からアクセスしないのだからと無精してTemplate使いたかったわけで多少本末転倒な気分もあるのだけれど、実作業では結局virtualすべき多態な事案になってしまったのでコレはコレでよしとしとく。 ※も1つアホだったのは、new で継承元メソッド上書きしてたものだから、後から根本を virtual に変えても orverrideすべきものがnewのままでコンパイル通っちゃってハマるワナ |