[英]Set no type for a static method in a generic class
Not a fan of Java, but Java allows not setting types for generic classes and in that case it threats the type as Object
type. 不是Java的狂热者,但是Java不允许设置通用类的类型,在这种情况下,它会将类型威胁为“ Object
类型”。 However, as far as I know, C# enforces setting the type of <T>
anytime the generic class has to be instantiated or simply speaking used. 但是,据我所知,C#在必须实例化或仅使用泛型类的任何时候强制设置<T>
的类型。 However, let's say that we have a generic class, and we need a static method in there which does not rely on the type of <T>
. 但是,假设我们有一个通用类,并且在其中需要一个不依赖<T>
类型的静态方法。
Firstly, we know that it can be moved to a separate context or we can set a dummy type of <T>
, but as a programming puzzle is there any way to call it Without defining the type of T
? 首先,我们知道可以将其移动到单独的上下文中,也可以将其设置为<T>
的伪类型,但是作为编程难题,有什么方法可以调用它而不定义T
的类型 ?
Example: 例:
class Test<T> where T: ITestable {
...
public static void CreateTestFile(String fileName) {...}
}
Test.CreateTestFile("test.txt");
This can be done Java and apparently can't be in C#. 可以使用Java完成此操作,显然不能使用C#。 But I just wanna make sure. 但我只想确定。
Java and C# implement generics differently: Java和C#实现泛型的方式有所不同:
Java uses type erasure , which basically means that at compile time, anything you put in <T>
is erased and becomes Object
. Java使用类型擦除 ,从根本上讲 ,这意味着在编译时,您放入<T>
被擦除并成为Object
。 Something<Foo>
and Something<Bar>
will be the same type at runtime, and wil be effectively equal to Something<Object>
. Something<Foo>
和Something<Bar>
在运行时将是相同的类型,并且实际上等于Something<Object>
。
C# uses run-time reification , meaning that for each type you use with a distinct T
, the runtime generates a new class altogether, by using the open generic version as a template (which means it also generates the underlying native code once per T
as you call it). C#使用运行时规范化 ,这意味着对于使用不同的T
每种类型,运行时通过使用开放的通用版本作为模板来总计生成一个新类(这意味着它还会为每个T
生成一次底层本机代码)。您称之为)。 Something<Foo>
and Something<Bar>
are two unrelated types as far as the CLR is concerned. 就CLR而言, Something<Foo>
和Something<Bar>
是两个不相关的类型。
Hopefully you understand why this difference is important to your scenario. 希望您理解为什么这种差异对您的情况很重要。 Ignoring T
is trivial in Java, but not so easy in C#. 在Java中忽略T
很简单,但在C#中却不那么容易。
If you don't need T
in your code, then use a non-generic method: 如果您的代码中不需要T
,请使用非泛型方法:
abstract class Test
{
public static void CreateTestFile(String fileName) {...}
}
class Test<T> : Test
where T : ITestable
{
...
}
Here, that's better :) 在这里,那更好:)
Also, note that for instance methods, you can use covariant and contravariant interfaces to loosen the requirement for a known T
at compile-time. 另外,请注意,对于实例方法,您可以使用协变和逆变接口在编译时放宽对已知T
的要求。 For instance, if you use a covariant interface, you only need to know a base type of T
. 例如,如果您使用协变接口,则只需知道T
的基本类型。
You should really consider separating your concerns, placing that public static method elsewhere. 您应该真正考虑分离您的关注点,将该公共静态方法放在其他地方。 However, if you really want to call it, this would work just fine: 但是,如果您真的要调用它,那么就可以了:
class Program
{
static void Main(string[] args)
{
Test<ITestable>.CreateTestFile("test.txt");
}
}
class Test<T> where T : ITestable
{
public static void CreateTestFile(String fileName) { }
}
public interface ITestable { }
If you had a constraint where T : class, new()
, you could do something similar: 如果您where T : class, new()
有一个约束,则可以执行类似的操作:
class Program
{
static void Main(string[] args)
{
Test<object>.CreateTestFile("test.txt");
}
}
class Test<T> where T : class, new()
{
public static void CreateTestFile(String fileName) { }
}
public interface ITestable { }
If you had an even weirder constraint like where T : class, ITestable, new()
I'd stop worrying about getting the compiler to jump through your hoops, rethink your design, and separate the concerns along these lines: 如果您有一个甚至更奇怪的约束,例如where T : class, ITestable, new()
我将不再担心让编译器跳入where T : class, ITestable, new()
,重新考虑您的设计,并按照以下where T : class, ITestable, new()
分离问题:
class Program
{
static void Main(string[] args)
{
Util.CreateTestFile("test.txt");
}
}
class Util
{
public static void CreateTestFile(String fileName) { }
}
class Test<T> where T : class, ITestable, new()
{
/*...*/
}
public interface ITestable { }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.