如何在C#中将通用对象分配给非泛型引用

时间:2011-05-13 13:04:25

标签: c# generics

我是一个Java人,并试图在C#中实现一些代码。我做了一个小时的研究,但找不到任何。 我有一个我声称为Generic的接口叫

interface TypeSerializer<T>

然后我有两个这样的实现。

class StringSerializer: TypeSerializer<String> 

class ByteArraySerializer: TypeSerializer<byte[]> 

现在我想创建一个包含这些实例的数组,并将数组引用为TypeSerializer。是这样的:

TypeSerializer[] serializers = 
new TypeSerializer[2] {new ByteArraySerializer(), new StringSerializer()};

此代码无法编译,但在Java中,类似的代码会编译。

我也试过了......

TypeSerializer<Object>[] serializers = 
new TypeSerializer<Object>[2] {new ByteArraySerializer(), new StringSerializer()};

仍然没有办法。

如何在不知道通用类型的情况下声明此数组并访问实例。

修改

基于下面的答案,很明显我应该有两个接口;有和没有通用。 这是接口方法。你能否告诉我们如何实施它们。

public interface ITypeSerializer<T>:TypeSerializer
{
    void write(BinaryWriter writer, T obj);
    T read(BinaryReader reader);
}

4 个答案:

答案 0 :(得分:5)

您可以创建泛型版继承的接口的非泛型版本,这会像往常一样强制实现类。

interface ITypeSerializer { }
interface ITypeSerializer<T> : ITypeSerializer { }
class StringSerializer : ITypeSerializer<string> { } // implements ITypeSerializer, too 

// non-generic array
ITypeSerializer[] serializers = ...

ITypeSerializer上需要的任何方法都应接受或返回object,其实现通常是泛型版本的传递方法。

一个实现示例:

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

实施ITypeSerializer<T>时,还需要提供ITypeSerializer方法的实现。一种常见的模式是显式地实现泛型和非泛型,这样非泛型方法只有在通过接口引用类时才可见。

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

注意非泛型方法是如何简单地传递给通用对应方的。

答案 1 :(得分:2)

您的界面可以这样声明:

interface TypeSerializer<out T>

“out”使您使用C#的通用方差功能,并且您将能够编译您尝试过的第二个表单:

TypeSerializer<Object>[] serializers = 
new TypeSerializer<Object>[2] {new ByteArraySerializer(), new StringSerializer()};

这适用于C#4.0及更高版本

答案 2 :(得分:1)

如果您不了解泛型类型,则使用通用接口并不理想。我很想使用:

interface ITypeSerializer {...}

使用与object一起使用的API。在大多数情况下,这不会出现问题 - 因为您最有可能序列化类(因此没有装箱)。偶尔演员会成为一个问题。

如果你真的想要,你可以拥有双通用/非通用API,但除非你需要它,这可能是一种过度杀戮(说有人花了 很多 时间与这个确切的场景非常相似)。

答案 3 :(得分:0)

这应该可以解决问题:

interface ITypeSerializer { }
interface ITypeSerializer<T> : ITypeSerializer { }

请注意,命名以大写I

开头的接口是C#约定