【问题标题】:How to assign a generic object to non generic reference in C#如何在 C# 中将泛型对象分配给非泛型引用
【发布时间】:2011-05-13 13:04:25
【问题描述】:

我是一名 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);
}

【问题讨论】:

  • 欢迎来到 C# 的光明世界 ;-)
  • @Steven 谢谢,在这个光明的世界里找不到自己的路:)

标签: c# generics


【解决方案1】:

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

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&lt;T&gt; 时,还需要提供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);
    }
}

请注意非泛型方法是如何简单地传递给泛型对应方/从泛型对应方传递。

【讨论】:

  • 你能不能也展示一下如何实现它我更新了这个问题。非常感谢。
【解决方案2】:

你的接口可以这样声明:

interface TypeSerializer<out T>

“out”让您使用 C# 的通用方差特性,您将能够编译您尝试过的第二种形式:

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

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

【讨论】:

  • 我使用的是 Mono,所以这不起作用? 没有编译。我应该使用任何命名空间吗?
  • 嗯,不确定那个。我认为 Mono 对 C# 4.0 特性有一些支持,但不能具体说明它是否具有这一特性。
【解决方案3】:

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

interface ITypeSerializer {...}

使用适用于 object 的 API。在大多数情况下,这不会出现问题 - 因为您很可能正在序列化类(所以没有装箱)。偶尔的演员阵容不会成为问题。

如果你真的想要,你可以拥有一个通用/非通用 API,但除非你需要它,否则这可能是矫枉过正(有人说花了 很多 几乎可以在这种情况下工作)。

【讨论】:

    【解决方案4】:

    这应该可以解决问题:

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

    请注意,命名接口以大写 I 开头是 C# 约定

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-01
      • 2012-03-24
      • 1970-01-01
      • 2010-10-19
      相关资源
      最近更新 更多