假设,我想创建一个仅可以将int
和double
作为类型的泛型类。
public class A<T> where T: int, double
{
public T property{get;set;}
}
例如:
A<int> i = new A<int>();
i.property = 10;
A<double> d = new A<double>();
d.property = 0.01;
但是,这不起作用。
我该怎么做?
我还有其他方法可以满足我的特定要求吗?
答案 0 :(得分:4)
C#中不存在这样的约束。但是对于值类型,您可以使用struct
作为一般约束。它仅允许非空值类型。
public class A<T> where T : struct
{
public T property;
}
您可以在构造函数中添加运行时类型检查:
public class A<T> where T : struct
{
public T property;
public A()
{
if(typeof(T) != typeof(int) || typeof(T) != typeof(double))
{
throw new InvalidConstraintException("Only int or double is supported");
}
}
}
答案 1 :(得分:3)
您可以编写自己的包装程序,并为其使用基本接口。例如:
public class Integer : IMyNumber
{
public int Value { get; set; }
public Integer() { }
public Integer( int value ) { Value = value; }
// Custom cast from "int":
public static implicit operator Integer( Int32 x ) { return new Integer( x ); }
// Custom cast to "int":
public static implicit operator Int32( Integer x ) { return x.Value; }
public override string ToString()
{
return string.Format( "Integer({0})", Value );
}
}
public interface IMyNumber
{
// nothing needed
}
然后您可以编写您的通用类:
public class A<T> where T : IMyNumber
{
public T property;
}
您可以使用它:
A<Integer> i = new A<Integer>();
i.property.Value = 10;
答案 2 :(得分:1)
您可以将private
构造函数添加到A<T>
类中,并声明两个相应的类:A_int
和A_double
内部,以便可以继承他们从A<T>
开始-对他们成为“友好” 到A<T>
。但是对于在该范围之外声明的类(Test
类),由于private
构造函数而无法直接创建,我们将不得不调用,但是不能。因此,实际上,您只有A<T>
的两个可用变体,并带有编译时间不允许使用的通知:
public class A<T> where T : struct
{
//constructor surely can have arguments
private A()
{
}
public T property { get; set; }
//and other common stuff
//each class declaration below we can treat like "where" constraint
public class A_int : A<int> { }
public class A_double : A<double> { }
}
//compile time error:
//'A<bool>.A()' is inaccessible due to its protected level
public class Test : A<bool>
{
}
用法:
using static NameSpaceName.A<int>;
//you should not care about <int> - it is only needed for compiler
//and won't have any influence
var intVar = new A_int();
var doubleVar = new A_double();
//compile time error:
//'A<decimal>.A()' is inaccessible due to its protected level
var decimalVar = new A<decimal>();
答案 3 :(得分:0)
您可以通过使用带有静态方法的工作区并使构造函数内部化来实现。 但是,仅当A <>在其他库中时,此方法才有效。如果所有内容都在同一个库中,则此解决方案将无法工作。
public class Program
{
public static void Main()
{
var a = A.CreateDecimal();
a.property = 7;
}
}
public class A<T>
{
public T property;
internal A()
{
}
}
public static class A
{
public static A<decimal> CreateDecimal() => new A<decimal>();
public static A<int> CreateInt() => new A<int>();
}
答案 4 :(得分:0)
据我对C#泛型的理解,您可以通过几种“模式”来设置泛型:
where T : class
或where T : BaseClass
甚至是where T : ISomeInterface
之类的过滤器,您可以在其中指定传入的类型必须严格地是一个类,一个继承自BaseClass或分别实现ISomeInterface的类型。据我所知,没有办法限制您可以使用的结构或基元。最好的选择是使用要使用的原始类型创建单独的实现。另外,您可以创建一个构造函数,以检查传入的类型是否与允许的类型匹配,以及是否引发异常。
public class MyGenericClass<T>
{
public MyGenericClass()
{
if(typeof(T) != typeof(int)) throw new Exception("You have passed an invalid type");
}
}
希望这会有所帮助。
答案 5 :(得分:0)
如果您唯一的目标是防止A与<p style="background-color: #000">
<button>
<svg width="25px" height="25px" xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 43.42 43.42">
<path d="M21.71,43.42A21.71,21.71,0,1,1,43.42,21.71,21.73,21.73,0,0,1,21.71,43.42ZM21.71,2A19.71,19.71,0,1,0,41.42,21.71,19.73,19.73,0,0,0,21.71,2Z" style="fill: rgb(255, 255, 255);"></path>
</svg>
</button>
或int
以外的其他任何东西一起使用,则可以使用。 XML注释至少可以告诉潜在的开发人员它们有限。
deouble