【问题标题】:How do I write a list using BinaryWriter?如何使用 BinaryWriter 编写列表?
【发布时间】:2011-07-20 22:20:04
【问题描述】:

我想使用一个通用的 WriteList(List value) 函数来使用 BinaryWriter 编写一个 List。这是我正在使用的代码:

public void WriteList<T>(List<T> value)
{
    for (int i = 0; i < value.Count; i++)
    {
        _writer.Write(value[i]);
    }
}

我收到的错误是:

 Error  1   The best overloaded method match for 'System.IO.BinaryWriter.Write(bool)' has some invalid arguments    
Error   2   Argument 1: cannot convert from 'T' to 'bool'   

BinaryFormatter 绝对不是一个选项。

【问题讨论】:

  • 对 T 有任何限制吗?像 T:struct?

标签: c# binarywriter


【解决方案1】:

我真的不认为你可以避免 BinaryFormatter。因为类型 T 可以是任何复杂类型,并且 T 的每个实例都可以表示内存上的巨大变量图。

所以您唯一的解决方案是将您的 T 实例转换为 byte[] 格式,最简单的解决方案是:BinaryFormatter

实际上 .Write() 方法只接受原始类型的原因是它知道如何将它们直接转换为 byte[](使用 Convert.ToXXX()),但对于泛型类型 T,它无法猜测。

作为一种变通方法,您可以定义这样的接口:

public interface IBinarySerializable
{
    byte[] GetBytes();
}

然后在你的类中实现它:

public class MyClass: IBinarySerializable
{
    public int X {get;set;}
    public byte[] GetBytes()
    {
        return BitConverter.GetBytes(X); // and anyother
    }
}

并将您的方法更改为:

public void WriteList<T>(List<T> value) where T:IBinarySerializable
{
    for (int i = 0; i < value.Count; i++)
    {
        _writer.Write(value[i].GetBytes());
    }
}

【讨论】:

    【解决方案2】:

    如果您查看 BinaryWriter 的文档,您会发现它不接受对象的参数(写入原始类型),并且编译器正在尽最大努力处理重载,但失败了,因为您不能将 T 转换为 bool 或 BinarwWriter 想要的任何其他内容。

    您必须将对象转换为 BinaryWriter 可以使用的对象。

    【讨论】:

    • 如...使用反射获取类的所有value-type成员,然后用BinaryWriter依次写入。不过,我认为这是您答案的一部分,因为这是您唯一可以使用的地方。
    • 是的,但谁愿意。如果你有一个引用类型作为成员的值类型(结构),你也可能会遇到问题。如果您真的想做某事,您可以实现一个自定义序列化程序以输出为 byte[] 或字符串等。需要一个真正的充分理由来执行此操作。
    • 说真的!我找到的唯一充分理由是因为您想要 Silverlight 中的 BinaryFormatter。
    【解决方案3】:

    您不能将泛型 T 传递给 BinaryWriter.Write - 它具有许多特定类型(bool、byte、byte[]、int、string 等)的重载,但没有泛型。所以你需要自己做,类似于下面的代码。

        public void WriteList<T>(List<T> value)
        {
            for (int i = 0; i < value.Count; i++)
            {
                switch (Type.GetTypeCode(typeof(T))){
                //_writer.Write(value[i]);
                    case TypeCode.Boolean:
                        _writer.Write((bool)(object)value[i]);
                        break;
                    case TypeCode.Byte:
                        _writer.Write((byte)(object)value[i]);
                        break;
                    case TypeCode.Char:
                        _writer.Write((char)(object)value[i]);
                        break;
                    case TypeCode.Decimal:
                        _writer.Write((decimal)(object)value[i]);
                        break;
                    case TypeCode.Double:
                        _writer.Write((double)(object)value[i]);
                        break;
                    case TypeCode.Single:
                        _writer.Write((float)(object)value[i]);
                        break;
                    case TypeCode.Int16:
                        _writer.Write((short)(object)value[i]);
                        break;
                    case TypeCode.Int32:
                        _writer.Write((int)(object)value[i]);
                        break;
                    case TypeCode.Int64:
                        _writer.Write((short)(object)value[i]);
                        break;
                    case TypeCode.String:
                        _writer.Write((string)(object)value[i]);
                        break;
                    case TypeCode.SByte:
                        _writer.Write((sbyte)(object)value[i]);
                        break;
                    case TypeCode.UInt16:
                        _writer.Write((ushort)(object)value[i]);
                        break;
                    case TypeCode.UInt32:
                        _writer.Write((uint)(object)value[i]);
                        break;
                    case TypeCode.UInt64:
                        _writer.Write((ulong)(object)value[i]);
                        break;
                    default:
                        if (typeof(T) == typeof(byte[]))
                        {
                            _writer.Write((byte[])(object)value[i]);
                        }
                        else if (typeof(T) == typeof(char[]))
                        {
                            _writer.Write((char[])(object)value[i]);
                        }
                        else
                        {
                            throw new ArgumentException("List type not supported");
                        }
    
                        break;
                }
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多