当前位置: 首页 > 面试题库 >

在.NET中获取Java类的行为

轩辕实
2023-03-14
问题内容

我在java中有一个通用类定义为:

public static class KeyCountMap<T> 
{
   private Map<T, MutableInt> map = new LinkedHashMap<T, MutableInt>();
   // ... rest of the properties...

   public KeyCountMap()  
   { }

   @SuppressWarnings({ "unchecked", "rawtypes" })  
   public KeyCountMap(Class<? extends Map> mapType) throws InstantiationException, IllegalAccessException   
   {
      map = mapType.newInstance();
   }  
   //... rest of the methods...  
}

我已经在.NET中将相同的类定义为:

public static class KeyCountMap<T>  
{  
   private Dictionary<T, MutableInt> map = new Dictionary<T, MutableInt>();
   // ... rest of properties...

   public KeyCountMap()  
   { }

   public void KeyCountMap<T>(T obj) where T : Dictionary<T, MutableInt>  
   {  
      obj = new T();  // Unable to define new instance of T
      map = obj;      // Unable to convert T to base class
   }  
}

然后定义了一种方法,以KeyCountMap<T>按值降序对类型图进行排序。该方法定义为:

public static KeyCountMap<T> SortMapByDescendValue<T>(KeyCountMap<T> _map)
{
   List<KeyValuePair<T, MutableInt>> _list = new List<KeyValuePair<T, MutableInt>>(_map.EntrySet());  
   // whereas _map.EntrySet() return of type HashSet<KeyValuePair<T, MutableInt>>  
   _list = _list.OrderByDescending(_x => _x.Value).ToList();

   KeyCountMap<T> _result = new KeyCountMap<T>();
   foreach (KeyValuePair<T, MutableInt> _entry in _list)
   {
       _result.Put(_entry.Key, _entry.Value);
   }
   return _result; 
}

如何更正.NET中定义的类?


问题答案:

我假设您知道Java在编译后会擦除所有通用类型信息(存在变量的元数据,但实际对象没有通用类型信息)。此外,您的代码不是类型安全的:

@SuppressWarnings({ "unchecked", "rawtypes" })

之所以使用它,是因为您正在创建的非参数化实例Map

在.NET中,您不会像这样绕过类型系统,因为通用类型信息会在运行时保留 并使用

让我们看看您的C#代码:

public static class KeyCountMap<T>

C#中的静态类是无法实例化的类,仅用于其静态成员。我想你不要这个。也许KeyCountMap是Java中的静态嵌套类,而不是内部类。

在C#中,您没有内部类。嵌套类不与包含类的实例共享数据,就好像包含类的名称是嵌套类的名称空间的一部分。因此,您不需要(实际上也不需要)static此处的关键字。

{  
   private Dictionary<T, MutableInt> map = new Dictionary<T, MutableInt>();

在.NET中,Dictionary是一个类。为了保持意图,您应该使用IDictionary对应的界面作为map字段的类型。

   // ... rest of properties...

   public KeyCountMap()  
   { }

   public void KeyCountMap<T>(T obj) where T : Dictionary<T, MutableInt>

为什么void返回类型,这不是构造函数吗?

在C#中,构造函数不能通用。您可能想要一个Type

您的C#代码没有任何意义,因此您可以执行以下操作:

   public KeyCountMap(Type dictionaryType)
   {
      if (!typeof(IDictionary<T, MutableInt>).IsAssignableFrom(dictionaryType))
      {
          throw new ArgumentException("Type must be a IDictionary<T, MutableInt>", nameof(dictionaryType));
      }
      map = (IDictionary<T, MutableInt>)Activator.CreateInstance(dictionaryType);
   }
}

在创建实例之前,我们正在检查类型。如果不这样做,我们将创建一个实例,强制转换将失败并且分配也不会发生,因此新实例将只是垃圾。

实际实例可能是代理。如果是这样,您可能不想在创建实例之前检查类型。

您不能只是将Java复制并粘贴为C#(反之亦然),并期望在它起作用之前进行一些更改,以定义一些 作品
,例如编译。这些语言不是很相似,而且有太多微妙的地方是错误的。

这种方法一开始可能很有趣,但是您会发现它时常绊倒,很快就会变得毫无乐趣。在开始逐行翻译代码之前,您应该学习基础知识并了解使用目标语言完成操作的方式。很多时候,您可能会发现在一种环境中必须要做的事情已经存在于另一种环境中,反之亦然,或者在另一种环境中可能需要采取更多或更少的步骤等等。

在这种特殊情况下,Java成为Class通用类,而.NET则保留Type非通用类。在.NET中,仅接口和委托可以声明通用类型的协方差或逆方差。无论如何,这都是限制性的,如果Type是通用的,则预期用途可以是协变的或逆变的。但是请记住,在Java中,Class<T>运行时的泛型与一样好Class,它在编译时仅具有任何值,并且您可以告诉编译器,无论如何您都更加了解,就像您所做的那样。



 类似资料:
  • 问题内容: 我该如何实现? 到目前为止,我尝试过的所有操作始终返回类型,而不是所使用的特定类型。 问题答案: 正如其他人所提到的,只有在某些情况下才能通过反思来实现。 如果你确实需要类型,这是通常的(类型安全的)解决方法:

  • 问题内容: 我该如何实现? 到目前为止,我尝试过的所有操作始终返回类型,而不是所使用的特定类型。 问题答案: 正如其他人所提到的,只有在某些情况下才能通过反射来实现。 如果你确实需要类型,这是通常的(类型安全)解决方法:

  • 问题内容: 我试图在另一个问题中从Spark库调用。并且,它要求两个参数,一个文字对象,它的类型(A )。 第一个论点,我可以提出自己(我认为)。但是对于第二个对象,我不知道如何为它实例化一个对象。我正在尝试通过作为第二个参数。 有人可以告诉我如何在 Java中* 创建for 吗?这是我要完成的代码: * 问题答案: 在另一个问题中,我说 并从Java提供CanBuildFrom自变量在技术上是可

  • 问题内容: 我只是想知道大多数人如何从Java文件中获取mime类型?到目前为止,我已经尝试了两个工具:。 第一个给我内存异常,第二个没有正确关闭其流。我只是想知道其他人是否拥有他们使用和正常工作的方法/库? 问题答案: 不幸, 之所以无法使用,是因为URL的这种使用将文件锁定了,例如,它是不可删除的。 但是,你有: 还有以下内容,其优点是不仅可以使用文件扩展名,而且还可以浏览内容 但是,正如上面

  • 问题内容: 我为Clojure添加了耐用性,最后我可以添加函数了。在Clojure中,使用调用方法(以及其他方法)将字节字节编译为类。这样,功能就是一流的。为了使这些持久化,我需要序列化和反序列化这些类。如何在不访问.class文件的情况下获取类的字节码? 如果我弄错了,请纠正我,但是使用代理程序需要产生一个单独的VM,并且该代理程序连接到第一个VM。我需要从同一台VM执行此操作。 仅使用Seri

  • 问题内容: 我创建了自己的注释类型,如下所示: 并将其附加到一个类上: 我试图通过反射来获得类注释,如下所示: 但它没有打印任何内容。我究竟做错了什么? 问题答案: 默认的保留策略是,默认情况下,注释信息在运行时不保留: 批注由编译器记录在类文件中,但VM在运行时无需保留。这是默认行为。 而是使用: 注释将由编译器记录在类文件中,并在运行时由VM保留,因此可以通过反射方式读取它们。 …您使用met