使用.NET Generics改进带有可变参数的方法

sbi*_*sbi 4 .net c# generics

我有很多功能,目前超载,int以及string:

bool foo(int);
bool foo(string);
bool bar(int);
bool bar(string);
void baz(int p);
void baz(string p);
Run Code Online (Sandbox Code Playgroud)

然后我有很多的功能取1,2,3,或二者之一的4个参数intstring,其调用上述功能:

void g(int p1)    { if(foo(p1)) baz(p1); }
void g(string p1) { if(foo(p1)) baz(p1); }

void g(int    p2, int    p2) { if(foo(p1)) baz(p1); if(bar(p2)) baz(p2); }
void g(int    p2, string p2) { if(foo(p1)) baz(p1); if(bar(p2)) baz(p2); }
void g(string p2, int    p2) { if(foo(p1)) baz(p1); if(bar(p2)) baz(p2); }
void g(string p2, string p2) { if(foo(p1)) baz(p1); if(bar(p2)) baz(p2); }

// etc.
Run Code Online (Sandbox Code Playgroud)

注意:该g()系列的实现只是一个例子

比当前更多类型intstring可能随时引入.对于参数多于4的函数也是如此.当前相同函数的数量几乎无法管理.在任一维度中再添加一个变体,组合爆炸将是如此巨大,它可能会吹走应用程序.

在C++中,我会被模板化g()并完成.

我知道.NET泛型是不同的.我一直在与他们战斗两个小时,现在试图提出一个不涉及复制和粘贴代码的解决方案,但无济于事.

C#泛型不要求我为一系列函数输入相同的代码,这些函数有三种类型的五种参数?

我错过了什么?

编辑:这些功能用于解析一串参数(目前要么intstring从一些来源).想象一下bar(),baz()并且能够读取两个int或者string,并且g()系列指定要解析的参数的类型和数量(隐式地,通过它们的参数的类型).

Jor*_*ira 5

考虑在这种情况下使用继承.我假设foo,bar并且baz是类型固有的(在您的情况下为int或字符串).如果不是这样,请更正或评论此答案.

using System;

namespace ConsoleApplication3
{
    abstract class Param
    {
        public abstract bool Foo();
        public abstract bool Bar();
        public abstract void Baz();

        public static IntParam Create(int value)
        {
            return new IntParam(value);
        }

        public static StringParam Create(string value)
        {
            return new StringParam(value);
        }
    }

    abstract class Param<T> : Param {
        private T value;

        protected Param() { }

        protected Param(T value) { this.value = value; }

        public T Value {
            get { return this.value; }
            set { this.value = value; }
        }
    }

    class IntParam : Param<int>
    {
        public IntParam() { }
        public IntParam(int value) : base(value) { }

        public override bool Foo() { return true; }
        public override bool Bar() { return true; }

        public override void Baz()
        {
            Console.WriteLine("int param value is " + this.Value);
        }
    }

    class StringParam : Param<string>
    {
        public StringParam() { }
        public StringParam(string value) : base(value) { }

        public override bool Foo() { return true; }
        public override bool Bar() { return true; }

        public override void Baz()
        {
            Console.WriteLine("String param value is " + this.Value);
        }
    }

    class Program
    {
        static void g(Param p1)
        {
            if (p1.Foo()) { p1.Baz(); }
        }

        static void g(Param p1, Param p2)
        {
            if (p1.Foo()) { p1.Baz(); }
            if (p2.Bar()) { p2.Baz(); }
        }

        static void Main(string[] args)
        {
            Param p1 = Param.Create(12);
            Param p2 = Param.Create("viva");

            g(p1);
            g(p2);
            g(p1, p1);
            g(p1, p2);
            g(p2, p1);
            g(p2, p2);

            Console.ReadKey();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这将输出:

int param value is 12
String param value is viva
int param value is 12
int param value is 12
int param value is 12
String param value is viva
String param value is viva
int param value is 12
String param value is viva
String param value is viva
Run Code Online (Sandbox Code Playgroud)

对于新支持的类型,您:

  1. 创建一个支持该类型和扩展的新类Param<T>;
  2. 实施Foo,BarBaz为这种新型;
  3. 创建一个g具有另一个参数的新方法(只有一个).

特别是3)这将大大减少方法的爆炸.现在,您g为任何给定数量的参数编写单个方法.使用以前的设计,您必须为n参数,2^n方法(n = 1 - > 2方法,n = 2 - > 4方法,n = 3 - > 8方法,...)编写.