【问题标题】:Set no type for a static method in a generic class不为泛型类中的静态方法设置类型
【发布时间】:2016-04-22 08:29:49
【问题描述】:

不是 Java 的粉丝,但 Java 不允许为泛型类设置类型,在这种情况下,它会将类型威胁为 Object 类型。但是,据我所知,C# 强制设置 <T> 的类型,只要泛型类必须被实例化或简单地说使用。但是,假设我们有一个泛型类,我们需要一个不依赖于<T> 类型的静态方法。

首先,我们知道它可以移动到一个单独的上下文中,或者我们可以设置一个虚拟类型<T>,但是作为一个编程难题有没有办法调用它不定义@987654325的类型@

例子:

 class Test<T> where T: ITestable {
     ...
     public static void CreateTestFile(String fileName) {...}
 }
 Test.CreateTestFile("test.txt");

这可以在 Java 中完成,但显然不能在 C# 中完成。但我只是想确定一下。

【问题讨论】:

  • 否,类型必须在调用或编译时填充,不能保持打开为T。您应该考虑将静态方法从这个泛型类中分离出来。
  • 只是出于好奇。正如我所说,我只是想确保 C# 不允许这样做。
  • 只要把方法放在非泛型类中就行了……如果和T无关,就没有理由放在Test&lt;T&gt;中。

标签: c# generics


【解决方案1】:

Java 和 C# 实现泛型的方式不同:

  • Java 使用类型擦除,这基本上意味着在编译时,您放入&lt;T&gt; 的任何内容都会被擦除并变成ObjectSomething&lt;Foo&gt;Something&lt;Bar&gt; 在运行时将是相同的类型,并且实际上等于 Something&lt;Object&gt;

  • C# 使用 run-time reification,这意味着对于您使用不同的 T 的每种类型,运行时通过使用开放的泛型版本作为模板(这意味着它还会为每个 T 生成一次底层本机代码)。就 CLR 而言,Something&lt;Foo&gt;Something&lt;Bar&gt; 是两个不相关的类型。

希望您了解为什么这种差异对您的方案很重要。忽略 T 在 Java 中是微不足道的,但在 C# 中却不是那么容易。

如果您的代码中不需要T,则使用非泛型方法:

abstract class Test
{
    public static void CreateTestFile(String fileName) {...}
}

class Test<T> : Test
    where T : ITestable
{
     ...
}

这里更好:)

另外,请注意,对于实例方法,您可以使用 covariantcontravariant 接口在编译时放宽对已知 T 的要求。例如,如果您使用协变接口,您只需要知道T 的基本类型。

【讨论】:

  • 不错的答案。不知道 Java 的实现。
【解决方案2】:

您真的应该考虑分离您的关注点,将公共静态方法放在其他地方。但是,如果您真的想调用它,这会很好:

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 { }

如果你有一个约束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 { }

如果你有一个更奇怪的约束,比如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 { }

【讨论】:

  • 想象一下 T 是where T: class, new(),而你不想设置类型。然后就不行了。
  • 没错,但是当你从不同的角度看东西时,会看到更多的场景。
  • 也许可以,但您确实冒着创建chameleon question 的风险,这对回答者来说并不好玩。
  • 再一次(不是刻薄:D)想象它是where T: class, ITestable, new()
猜你喜欢
  • 2012-02-10
  • 2010-10-16
  • 1970-01-01
  • 2010-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多