是否有一个合理的方法来;“违约”;C#泛型中的类型参数? 在C++模板中,可以指定某个类型参数是默认的。即,除非明确规定,否则将使用T型

是否有一个合理的方法来;“违约”;C#泛型中的类型参数? 在C++模板中,可以指定某个类型参数是默认的。即,除非明确规定,否则将使用T型,c#,generics,types,default,parameters,C#,Generics,Types,Default,Parameters,这可以用C#来表示或近似表示吗 我要找的东西是: public class MyTemplate<T1, T2=string> {} 基本上是: MyTemplate<int, string> t = new MyTemplate<int, string>(); MyTemplate t=newmytemplate(); 最后,我看到了一个例子,其中有一个模板被广泛使用,但我正在考虑使用一个额外的类型参数进行扩展。我想我可以子类化,但我很好奇是否还有其他

这可以用C#来表示或近似表示吗

我要找的东西是:

public class MyTemplate<T1, T2=string> {}
基本上是:

MyTemplate<int, string> t = new MyTemplate<int, string>();
MyTemplate t=newmytemplate();

最后,我看到了一个例子,其中有一个模板被广泛使用,但我正在考虑使用一个额外的类型参数进行扩展。我想我可以子类化,但我很好奇是否还有其他选择

子类化是最好的选择

我将为您的主要泛型类划分子类:

class BaseGeneric

有一个特定的类

class MyGeneric:BaseGeneric

这使得将逻辑保持在一个位置(基类)很容易,但也很容易提供这两种使用选项。根据不同的类别,可能只需要很少的额外工作即可实现此功能。

C#不支持此功能


正如您所说,您可以对它进行子类化(如果它没有被密封,并复制所有构造函数声明),但这是一件完全不同的事情。

不幸的是,C#不支持您尝试执行的操作。考虑到参数的默认类型必须遵守泛型约束,并且在CLR试图确保类型安全时很可能会造成麻烦,这将是一个很难实现的特性。

一个解决方案是子类化。我将使用的另一种方法是工厂方法(结合var关键字)

公共类MyTemplate
{
公共MyTemplate(…参数..){…}//构造函数
}
公共静态类MyTemplate{
公共静态MyTemplate创建(…参数..)
{
返回新的MyTemplate(…参数…);
}
公共静态MyTemplate创建(…参数…)
{
返回新的MyTemplate(…参数…);
}
}
var val1=MyTemplate.Create();
var val2=MyTemplate.Create();
在上述示例中,
val2
属于
MyTemplate
类型,而不是从中派生的类型

MyStringTemplate:MyTemplate的类型与MyTemplate的类型不同。 在某些情况下,这可能会带来一些问题。
例如,您不能将
MyTemplate
的实例强制转换为
MyStringTemplate

您还可以创建一个类重载,如下所示

public class MyTemplate<T1, T2> {
    public T1 Prop1 { get; set; }
    public T2 Prop2 { get; set; }
}

public class MyTemplate<T1> : MyTemplate<T1, string>{}
公共类MyTemplate{
公共T1 Prop1{get;set;}
公共T2 Prop2{get;set;}
}
公共类MyTemplate:MyTemplate{}

啊……这很有道理。如果类型参数提供唯一的签名,是否允许类型名称相同?@ee:是的,泛型可以通过参数计数进行重载。@ee:是的,但我会小心这样做。在.NET中这样做是“合法的”,但可能会导致混乱。我希望字符串派生类型的名称类似于主泛型类(因此很明显它是什么/很容易找到),但名称使它明显是字符串。@Reed:这真的会导致混淆吗?对于这个特定的案例,我认为同名甚至有帮助。NET中有一些例子做了同样的事情:例如Func委托。例如,谓词只是Func,但由于其用途不同而被重命名。实际上并非如此。它可以使用一个属性(如VB.NET中的默认参数)完成,并在编译时让编译器替换它。主要原因是C#设计目标。编译器必须确保默认参数满足通用约束。此外,默认参数本身将是泛型约束,因为对方法中的类型参数所做的任何假设都要求任何非默认类型参数从中继承。@Andrew,默认参数不必是泛型约束。如果这更像是C++中的默认模板参数,那么在AutoTalm的类上扩展它将是非常好的:MyTabeX=NULL,因为T2没有泛型约束,所以尽管默认类型的字符串,S浮是很好的。在这种情况下,默认模板参数本质上只是将MyTemplate作为MyTemplate的缩写编写的“语法糖”。@Andrew,我同意C#编译器应该验证这些默认模板参数是否满足现有的泛型常量。C#编译器已经在类声明中验证了一些类似的东西,例如,在Reed的BaseGeneric类中添加一个泛型约束,如“where U:ISomeInterface”,然后MyGeneric将无法编译并出现错误。验证一个默认模板参数将非常相似:编译器在声明一个类时进行验证,错误消息可能相同或非常相似。“这将是一个难以实现的特性”这是胡说八道。这将是微不足道的实施。根据模板约束验证类型的工作并不困难,因为候选类型出现在文件中的不同位置(即在模板中,而不是在模板实例化时)。这是最有用的方法。非常好的解决方案请在发布迟交的答案之前阅读其他答案,因为您的答案可能与其他答案相同。接受的答案是创建一个具有不同名称的类,我的解决方案是重载相同的类否,两者都在创建一个新类。这里的名字不重要
MyTemplate
MyTemplate
是一个不同的类,也不是另一个
MyTemplate
的类。即使实际类型不同,这是清楚和正确的,如果保持相同的名称,编码也会更容易。不是每个人都清楚类“重载”可以这样使用@DannyChen是对的-从技术角度来看,结果是一样的,但这个answear更接近OP要求的结果。不幸的是,这个解决方案仍然不如真正的“默认”通用参数,因为
public class MyTemplate<T1,T2>
{
     public MyTemplate(..args..) { ... } // constructor
}

public static class MyTemplate{

     public static MyTemplate<T1,T2> Create<T1,T2>(..args..)
     {
         return new MyTemplate<T1, T2>(... params ...);
     }

     public static MyTemplate<T1, string> Create<T1>(...args...)
     {
         return new MyTemplate<T1, string>(... params ...);
     }
}

var val1 = MyTemplate.Create<int,decimal>();
var val2 = MyTemplate.Create<int>();
public class MyTemplate<T1, T2> {
    public T1 Prop1 { get; set; }
    public T2 Prop2 { get; set; }
}

public class MyTemplate<T1> : MyTemplate<T1, string>{}