2

In Java, I can do that:

class JavaClass<A, B>{
    A first;
    B second;
}

And then declare an array, a list, or a single object of that type, without supplying generic parameters. They're being automatically converted to Object's, like in an example below:

JavaClass someArray = new JavaClass[4];

Now, the type of someArray[0].first is Object.

In C#, it doesn't seem to work:

class Leaderboard<UserType, UIEntry> 
    where UserType : User
    where UIEntry : UserUIEntry{}

And the declaration:

Leaderboard someLeaderboard = new Leaderboard();

Gives:

Using the generic type Leaderboard requires two type arguments.

Is there any equivalent to make this work and allow me to declare that?

Jacob
  • 351
  • 2
  • 9
  • Interesting concept... I don't think c# have anything like that. – Zohar Peled Jul 16 '18 at 21:07
  • 2
    Please see: [What is a raw type and why shouldn't we use it?](https://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it). – Turing85 Jul 16 '18 at 21:09
  • 4
    Java fakes generics via type erasure - C# has real generics, where `Foo` and `Foo` are real distinct types, so: no – Marc Gravell Jul 16 '18 at 21:14
  • Since arrays are covariant an retained, while generics are invariant and erased, the mixture of both arrays and generics is a recipe for trouble. You can take a look at [OpenJDK's `ArrayList` implementation](http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/util/ArrayList.java) for a possible solution. – Turing85 Jul 16 '18 at 21:16
  • This doesn't really address your question (like @Turing85 does), but one thing you can do to reduce typing for a generic class like `public class MyClass` when T is expected to be a big long type name is to create a non-generic static factory class with a create method. `public static class MyClass { public static MyClass Create(T forSomeT) {} }`. This isn't always appropriate, but it's sometimes much easer to type `var myObj = MyClass.Create(someObject)`than it is to type `var myObj = new MyClass ();` – Flydog57 Jul 16 '18 at 21:20

1 Answers1

4

First of all, generics in C# and Java are very different, both conceptually and implementation-wise. C# has so-called reified generics, while Java uses type erasure. Therefore, looking for similarities between these two languages in generics is usually not a good idea.

In C#, Leaderboard and Leaderboard<UserType, UIEntry> are two distinct types. If you really want to, you can write

class Leaderboard<UserType, UIEntry> where UserType : User where UIEntry : UserUIEntry{} class Leaderboard : Leaderboard<User, UserUIEntry>{}

and then use just new Leadeboard() (relying on inheritance). However, I wouldn’t think this is an especially great idea, trading a few keystrokes for worse readability.

Look how e.g. Tuple does it: Tuple is a nongeneric helper for the generic Tuple<...> class, containing a static .Create function which helps with type inference, reducing the need to write the generic parameters explicitly.

Mormegil
  • 7,955
  • 4
  • 42
  • 77
  • Yeah! Thanks for the answer. The only problem with that solution is that I still can't store that type in a single container, like `List` - which was the main issue here. – Jacob Jul 17 '18 at 05:34