C# 通用方法,其中T为类型1或类型2
是否有方法声明泛型函数的泛型类型为type1或type2 例如:C# 通用方法,其中T为类型1或类型2,c#,.net,generics,compiler-construction,C#,.net,Generics,Compiler Construction,是否有方法声明泛型函数的泛型类型为type1或type2 例如: public void Foo<T>(T number) { } public void Foo(T编号) { } 我可以将T约束为int或long吗 这没有道理T在方法中没有任何可用的编译时类型 相反,您应该创建两个重载方法。我认为这在当前是不可能的 关于创建一个数学库的讨论涵盖了相同的领域,并包含了一些解决方法。虽然可以使用a来限制每个泛型参数T的类型,但不幸的是,没有一个允许您在编译时强制执行T是类型1还是类
public void Foo<T>(T number)
{
}
public void Foo(T编号)
{
}
我可以将T约束为int或long吗
这没有道理T
在方法中没有任何可用的编译时类型
相反,您应该创建两个重载方法。我认为这在当前是不可能的 关于创建一个数学库的讨论涵盖了相同的领域,并包含了一些解决方法。虽然可以使用a来限制每个泛型参数T的类型,但不幸的是,没有一个允许您在编译时强制执行T是
类型1还是类型2
也没有任何方法在编译时强制您的泛型参数只能是任何基元类型(int、long、double等)。请改用重载方法:
public void Foo(int number)
{
}
public void Foo(long number)
{
}
无论如何,您不能对泛型类型执行算术运算。请注意,您可以将int
值传递给long
参数。它将自动转换为long
。因此,只使用一个带有长
参数的方法就足够了
旧的编程语言遵循“只能有一种”的原则。C#允许您在同一类、接口或结构中使用多个同名方法。这些方法必须具有不同的签名。这意味着,它们必须具有不同数量的参数或具有不同类型(或两者兼有)的参数。这就是所谓的方法重载。我知道这是一个老问题,这并不能完全回答它,但你可以用一个方法,而不是创建多个,或使用一般约束。。。如果您有20多种类型需要检查,则此功能尤其有用 显然,您不会像使用约束时那样进行编译器类型检查,但这在某些情况下会有所帮助
public void MyMethod<T>()
{
if (!typeof(T).Equals(typeof(int)) &&
!typeof(T).Equals(typeof(long)))
throw new Exception("T must be int or long");
//your logic here
}
public void MyMethod()
{
如果(!typeof(T).等于(typeof(int))&&
!typeof(T).等于(typeof(long)))
抛出新异常(“T必须是int或long”);
//你的逻辑在这里
}
我也遇到了这个问题,我认为我找到了更好的解决方案(假设您的方法的重载版本是不够的):
混合Type1
和Type2
没有任何相似之处是没有任何意义的,正如已经写过的那样。因此,对于这两种对象类型,都必须访问任何方法或属性。要确保编译器的这些方法或属性可用于您的对象,请通过创建接口MyInterface
并通过Type1
和Type2
实现,对Type1
和Type2
进行分组:
interface MyInterface {
void MyCommonMethod();
bool MyCommonProperty { get; }
}
class Type1 : MyInterface {
void MyCommonMethod() {
// TODO: Implement it for Type1
}
bool MyCommonProperty {
get {
// TODO: Implement it for Type1
}
}
}
class Type2 : MyInterface {
void MyCommonMethod() {
// TODO: Implement it for Type2
}
bool MyCommonProperty {
get {
// TODO: Implement it for Type2
}
}
}
现在,要将Foo
方法重写为同时接受Type1
和Type2
,请将constraintT
约束为MyInterface
对象:
public void Foo<T>(T number) where T : MyInterface
{
throw new NotImplementedException();
}
public void Foo(T编号),其中T:MyInterface
{
抛出新的NotImplementedException();
}
我觉得这可能会有帮助 对于ReferenceType对象,您可以执行以下操作
public void DoIt<T>(T someParameter) where T : IMyType
{
}
对于您的情况,使用long-as参数将限制对long和int的使用
public void DoIt(long someParameter)
{
}
要约束到任何值类型(如:int、double、short、decimal),可以使用:
public void DoIt<T>(T someParameter) where T : struct
{
}
public void DoIt(T someParameter),其中T:struct
{
}
有关更多信息,您可以查看官方文档@BoltClock,因为当参数不是基元(int、long、double…)时,我的代码会中断,我希望在编译时得到与运行时无关的错误:我认为这是有意义的。我有一个代码,如果你传递了一个不同的参数,那么double,decimal,float,int,long等都会停止。我想在编译时验证这一点。没道理吗?@gdoron:从你的观点来看,这是有道理的。从编译器的角度来看,这是没有意义的,因为
T
将不是一个可用的类型。在这种情况下,编译器可以将T
视为type1和type2的公共类型,其中没有任何关系T
是对象
。。如果你在字里行间阅读,我认为这是一个合理的问题。似乎他在要求一个约束,例如其中T:number
,不幸的是,它不存在。不过,这将是一个有意义的构造……我不能为每种数值类型编写20个方法。这是泛型应该具备的功能。泛型类型参数上不支持类似操作。有关示例,请参见System.Text.StringBuilder
。它为不同类型定义了20多个Append()
重载。这是否仅适用于接口?是否允许使用基类?@liang是的,您可以使用基类或基类抽象类或接口。
public void DoIt<T>(T someParameter) where T : struct
{
}