Click to See Complete Forum and Search --> : Java programmer has question about Generics


xusword
April 2nd, 2009, 10:55 AM
Hi all

I was a Java programmer, I am used to doing something as followed:

IO Example: (It's not the best example I can come up with, but it is the simplest one)


public interface IO<T>{
T parse(stream s);
String print(T o);
}



public class IOA extends IO<A>{
A parse(stream s){
A instanceA;
// parse A
return instanceA;
}

String print(A a){
return a.toString();
}
}



public class IOB extends IO<B>{
B parse(stream s){
A instanceA;
//parse B
return instanceB;
}


String print(B b){
return b.toString();
}
}


so far, everything can translate to C#
BUT
I cannot find a way to translate the following to C#



public class Peeker{

public Parser<?> peekAndFindSuitableParser(stream s){

// peeking.... then determine
if (/* need to return parserA */...){
return new ParserA();
}
else if (/* need to return parserB */...){
return new ParserB();
}

}
}



Is it possible to translate this to C#?
If not, should I just remove all the generics in these code?

MadHatter
April 3rd, 2009, 12:17 AM
.net doesn't have the concept of an anonymous generics parameter types.

since I have no clue what you're really trying to achieve, suggestions on how to implement what you need would be pointless.

It seems that if you're returning a parser object which is strongly typed (to your anonymous type) you wouldn't be able to reference the type returned from parse as its actual type anyway, so using its base type (object) would probably be the best route to take.

in .net generics provide you with a means to treat generic parameters by their actual types (instead of casting to/from System.Object). .net also has reference and value types, which are dealt with differently in memory, and whenever a value type is stored as an object, it is boxed / unboxed to a reference type. Generics remove that constraint.

perhaps if you describe what it is you are trying to accomplish, someone might be able to help with a design that fits your needs.

boudino
April 3rd, 2009, 02:57 AM
This is not possible in C#, because C# deals with generics in other way than Java. In C#, there is no type erasure, the type parameter is striped in compilation, but is presented in resulted byte code too.

Theoreticaly, if A and B would be types of the same inheritance hierarchy, you could use contravariance, but you have to hack it directly in IL code, because C# doesn't support it.

To achieve what is seems you want, you need to have an extra genericless interface, which you will return in peekAndFindSuitableParser() method.

Sometring like this:

public class A { }
public class B { }

public interface IO
{
Object parse(Stream s);
String print(Object o);
}

public interface IO<T>
{
T parse(Stream s);
String print(T o);
}

public abstract class Parser : IO
{
public Object parse(Stream s)
{
Object instance;
instance = new Object(); // there must be something better

return instance;
}

public string print(object o)
{
return o.ToString();
}
}

public class ParserA : Parser, IO<A>
{
public A parse(Stream s)
{
A instanceA;
instanceA = new A();
return instanceA;
}

public String print(A a)
{
return a.ToString();
}

public String print(Object a)
{
return a.ToString();
}
}

public class ParserB : Parser, IO<B>
{
public B parse(Stream s)
{
B instanceB;
instanceB = new B();
return instanceB;
}

public String print(B b)
{
return b.ToString();
}

public String print(Object b)
{
return b.ToString();
}
}

public class Peeker
{
public Parser peekAndFindSuitableParser(Stream s)
{
if (1 == 1)
{
return new ParserA();
}
else if (2 == 2)
{
return new ParserB();
}
}
}


I know it is exactly what you want, but I have no better idea. At least with the idea of completely changing the design, of course.