I am a Java guy, and trying to implement some code in C#. I did a research for an hour but couldn't find any. I have an开发者_开发百科 interface that I declared as Generic called
interface TypeSerializer<T>
Then I have two implementation of this.
class StringSerializer: TypeSerializer<String>
and
class ByteArraySerializer: TypeSerializer<byte[]>
Now I want to create an array with these instances and refer to array as TypeSerializer. Sth like this:
TypeSerializer[] serializers =
new TypeSerializer[2] {new ByteArraySerializer(), new StringSerializer()};
This code doesn't compile, however in Java a similar code does compile.
I also tried sth
TypeSerializer<Object>[] serializers =
new TypeSerializer<Object>[2] {new ByteArraySerializer(), new StringSerializer()};
still no way.
How should I declare this array and reach to the instances without knowing the Generic Type.
EDIT
Based on the answers below it becomes clear that I should have two interfaces; with and without generic. Here is the Interface methods. Could you please show also how to implement them.
public interface ITypeSerializer<T>:TypeSerializer
{
void write(BinaryWriter writer, T obj);
T read(BinaryReader reader);
}
You can create a non-generic version of the interface that the generic version inherits, which forces the implementations to the classes as usual.
interface ITypeSerializer { }
interface ITypeSerializer<T> : ITypeSerializer { }
class StringSerializer : ITypeSerializer<string> { } // implements ITypeSerializer, too
// non-generic array
ITypeSerializer[] serializers = ...
Any method that you need on ITypeSerializer
should either accept or return object
, with the implementations typically being pass-through methods for the generic versions.
An implementation example:
public interface ITypeSerializer
{
void Write(BinaryWriter writer, object obj);
object Read(BinaryReader reader);
}
public interface ITypeSerializer<T> : ITypeSerializer
{
void Write(BinaryWriter writer, T obj);
T Read(BinaryReader reader);
}
When you implement ITypeSerializer<T>
, you also need to provide implementations for the ITypeSerializer
methods. A common pattern is to implement the generic implicitly and the non-generic explicitly, so that the non-generic methods are only visible when referring to the class via the interface.
class StringSerializer : ITypeSerializer<string>
{
// implicit implementation of ITypeSerializer<string>
public void Write(BinaryWriter writer, string obj)
{
// provide core implementation here
}
public string Read(BinaryReader reader)
{
// provide core implementation here
}
// explicit implementation of ITypeSerializer
void ITypeSerializer.Write(BinaryWriter writer, object obj)
{
if (!(obj is string)) throw new ArgumentException("obj");
this.Write(writer, (string)obj);
}
object ITypeSerializer.Read(BinaryReader reader)
{
return this.Read(reader);
}
}
Notice how the non-generic methods are simply passing to/from the generic counterparts.
Your interface can be declared like this:
interface TypeSerializer<out T>
the "out" makes your uses the generic variance feature of C#, and you'll be able to compile the second form you tried:
TypeSerializer<Object>[] serializers =
new TypeSerializer<Object>[2] {new ByteArraySerializer(), new StringSerializer()};
This will work in C# 4.0 and later
If you aren't going to know the generic type, it isn't ideal to use a generic interface. I would be tempted to use:
interface ITypeSerializer {...}
with an API that works with object
. In most cases, this will not present an issue - as you are most likely serializing classes (so no boxing). The occasional cast is not going to be an issue.
If you really want, you can have a dual generic/non-generic API, but unless you need it that is probably overkill (says someone who has spent a lot of time working with pretty-much this exact scenario).
This should do the trick:
interface ITypeSerializer { }
interface ITypeSerializer<T> : ITypeSerializer { }
Note that it's C# convention to name interfaces starting with a capital I
精彩评论