Getting Java Class Behavior <? extends Map> in .NET.

I have a generic class in java defined as:

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

I defined one class in .NET as:

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

And then a method is defined for sorting a card of type KeyCountMap<T> by value in descending order. The method is defined as:

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

How can I fix a class defined in .NET?

0
java generics inheritance instantiation c #
Jun 14 '16 at 7:53 on
source share
3 answers

I assume that you know that after compilation, Java erases any information of a general type (there is metadata for variables, but the actual objects are devoid of information about the general type). In addition, your code is not type safe:

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

You use this because you are creating an unparameterized Map instance.

In .NET, you will not get around a type system like this because generic type information is stored and used at runtime.

Check out your C # code:

 public static class KeyCountMap<T> 

A static class in C # is a class that cannot be instantiated; it is used only for its static members. I think you don’t want it. Perhaps KeyCountMap is a static nested class in Java, not an inner class.

In C #, you have no inner classes. Nested classes do not share data with an instance of the containing class; as it were, the name of the containing class is part of the namespace for the nested class. So you don't need, and really don't need, the static .

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

In .NET, Dictionary is a class. To preserve the intent, you must use the IDictionary , the appropriate interface, as the type of the Map field.

  // ... rest of properties... public KeyCountMap() { } public void KeyCountMap<T>(T obj) where T : Dictionary<T, MutableInt> 

Why is the void return type not a constructor?

In C #, constructors cannot be shared. You probably need Type .

Your C # code just doesn't make sense, so here is what you could do:

  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); } } 

We check the type before instantiating. If we didn’t do this, we would create an instance, the cast would not work, and the assignment would not happen, so the new instance will be just garbage.

Perhaps the actual instance will be a proxy; If so, you may not want to check the type before instantiating it.




You cannot just copy-paste Java as C # (or vice versa) and expect to make only a few changes until they work, for some definition of work, for example. it compiles. The languages ​​are not so similar, and it is likely that too many subtle things are wrong.

This approach may be interesting at first, but you will stumble so often that it will soon cease to be generally fun. You must learn the basics and understand how everything is done in the target language before you begin translating the code line by line. Many times you may find that something that you needed to do in one environment already exists in another or vice versa, or something may take more or less steps for others, etc.

In this particular case, Java made Class universal class, and .NET retained Type not a generic class. In .NET, only interfaces and delegates can indicate general covariance or contravariance. In any case, this is pretty restrictive, if Type is generic, the intended use can be either covariant or contravariant. But remember that in Java, the generic Class<T> at runtime is as good as Class , it only has some value at compile time, and you can say that the compiler you know better is somehow and you.

+1
Jun 14 '16 at 10:52
source share
β€” -

There are two problems. First, you need to tell the compiler that T has a constructor without parameters, so you can call new T() . You can do this by providing the new() argument to the class definition.

You should also tell the compiler that T is actually the dictionary you are trying to assign, so we need to extend the class a little more:

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

Note that K is a key type of dictionary that you have not yet specified.

Secondly, T in your method may be a different T than in your class. Omitting this will do the trick:

 public void Map() { var obj = new Dictionary<K, MutableInt>(); // Unable to define new instance of T map = obj; // Unable to convert T to base class } 
+1
Jun 14 '16 at 7:56
source share

Perhaps this is what you want?

 public class KeyCountMap<T> where T : new() { private Dictionary<T, MutableInt> map = new Dictionary<T, MutableInt>(); // ... rest of properties... public KeyCountMap() { } public KeyCountMap(T obj) { obj = new T(); map = (Dictionary<T, MutableInt>)(object)obj; } } 
0
Jun 14 '16 at 10:19
source share



All Articles