C# 通用方法,其中T为类型1或类型2

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还是类

是否有方法声明泛型函数的泛型类型为type1或type2

例如:

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
,请将constraint
T
约束为
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
{

}