我在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>按值降序对类型图进行排序。该方法定义为:
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。
Map
在.NET中,您不会像这样绕过类型系统,因为通用类型信息会在运行时保留 并使用 。
让我们看看您的C#代码:
public static class KeyCountMap<T>
C#中的静态类是无法实例化的类,仅用于其静态成员。我想你不要这个。也许KeyCountMap是Java中的静态嵌套类,而不是内部类。
KeyCountMap
在C#中,您没有内部类。嵌套类不与包含类的实例共享数据,就好像包含类的名称是嵌套类的名称空间的一部分。因此,您不需要(实际上也不需要)static此处的关键字。
static
{ private Dictionary<T, MutableInt> map = new Dictionary<T, MutableInt>();
在.NET中,Dictionary是一个类。为了保持意图,您应该使用IDictionary对应的界面作为map字段的类型。
Dictionary
IDictionary
map
// ... rest of properties... public KeyCountMap() { } public void KeyCountMap<T>(T obj) where T : Dictionary<T, MutableInt>
为什么void返回类型,这不是构造函数吗?
void
在C#中,构造函数不能通用。您可能想要一个Type。
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,它在编译时仅具有任何值,并且您可以告诉编译器,无论如何您都更加了解,就像您所做的那样。
Class
Class<T>