通用方法,其中T是type1或type2

问题描述 投票:24回答:7

有没有办法声明泛型类型是type1还是type2的泛型函数?

例:

public void Foo<T>(T number)
{
}

我可以将T约束为int或long

c# .net generics compiler-construction
7个回答
15
投票

虽然您可以使用generic constraint来限制每个泛型参数T的类型,但不幸的是,没有任何一个允许您在编译时强制执行T是否为type1 or type2

也没有任何方法可以在编译时强制执行泛型参数只能是任何基本类型(int,long,double,...)。


15
投票

对于ReferenceType对象,您可以执行此操作

public void DoIt<T>(T someParameter) where T : IMyType
{

}

...

public interface IMyType
{
}

public class Type1 : IMyType
{
}

public class Type2 : IMyType
{
}

对于你的情况,使用long as参数会将使用限制为long和int无论如何。

public void DoIt(long someParameter)
{

}

限制为可以使用的任何值类型(如:int,double,short,decimal):

public void DoIt<T>(T someParameter) where T : struct
{

}

有关更多信息,您可以查看官方文档here


7
投票

没有。

这没有意义; T在该方法中没有任何可用的编译时类型。

相反,你应该制作两个重载方法。


5
投票

改为使用重载方法:

public void Foo(int number)
{
} 

public void Foo(long number)
{
}

无论如何,您无法对泛型类型执行算术运算。请注意,您可以将int值传递给long参数。它会自动转换为long。因此,只有一个带有long参数的方法就足够了。

较旧的编程语言遵循“只能有一个”原则。 C#允许您在同一个类,接口或结构中使用多个具有相同名称的方法。这些方法必须具有不同的签名。这意味着它们必须具有不同数量的参数或具有不同类型(或两者)的参数。这称为方法重载。


1
投票

我知道这是一个老问题,但这并不能完美地回答它,但是你可以用一个方法来做,而不是创建倍数,或者使用通用约束...如果你有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
}

0
投票

我认为目前不可能。

This question关于创建一个涵盖相同基础的数学库,并包括一些解决方法。


0
投票

我也有这个问题,我想我找到了一个更好的解决方案(假设你的方法的重载版本不足):

混合Type1Type2没有任何相似之处没有任何意义,因为已经写过。因此,必须为两种对象类型访问任何方法或属性。为了确保编译器可以为您的对象提供这些方法或属性,可以通过创建接口Type1并通过Type2MyInterface实现它来对Type1Type2进行分组:

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方法接受Type1Type2,约束T成为MyInterface对象:

public void Foo<T>(T number) where T : MyInterface
{
  throw new NotImplementedException();
}

我这可能会有所帮助。 :)

© www.soinside.com 2019 - 2024. All rights reserved.