繁体   English   中英

C#:如何制作类型泛型方法(字节/字/双字)?

[英]C#: How to make a Type generic method(byte/word/dword)?

我是泛型新手,我在C#中只能找到List [T]-没有别的。

这是我必须在C#中翻译的C ++代码

template <class type>
type Read()
{
    type t;
    int s = sizeof(type);
    if(index + s > size)
        throw(std::exception("error 101"));
    memcpy(&t, stream + index, s);
    index += s;
    return t;
}   

像那样

BYTE mode = Read<BYTE>();
DWORD mode1 = Read<DWORD>();
WORD mode2 = Read<WORD>();

问题:如何使用C#泛型呢?

这是一个功能模板。 您需要使用C#编写的类,但是类似:

public static class Utility 
{
    public static Type Read<Type>()
    {
        //Converted code to c# that returns a Type;
    }
}

您可能需要为此使用约束,例如限制为值类型。

您可以这样调用函数:

Utility.Read<int>();

您的代码似乎模仿BinaryReader类的ReadInt16ReadInt32ReadInt64方法。

没有全局变量的知识就很难进行重写。 假设流是字节数组,则以下代码将起作用。

public T Read<T>() where T : struct {
  // An T[] would be a reference type, and alot easier to work with.
  T[] t = new T[1];

  // Marshal.SizeOf will fail with types of unknown size. Try and see...
  int s = Marshal.SizeOf(typeof(T));
  if (_index + s > _size)
    // Should throw something more specific.
    throw new Exception("Error 101");

  // Grab a handle of the array we just created, pin it to avoid the gc
  // from moving it, then copy bytes from our stream into the address
  // of our array.
  GCHandle handle = GCHandle.Alloc(t, GCHandleType.Pinned);
  Marshal.Copy(_stream, _index, handle.AddrOfPinnedObject(), s);

  _index += s;

  // Return the first (and only) element in the array.
  return t[0];
}

您要查找的签名是:

public class Reader
{
    public static T Read<T>()
    {
    }
}

您需要将其放入类型中。 它可以是实例或静态成员。


编辑:

它与其他任何方法一样使用,除了必须显式传递泛型类型参数。 例如:

byte mode = Reader.Read<byte>()

看看MSDN上的C#泛型简介一文。 在那之后应该不言自明...

我只想指出,您的C ++示例充满了全局变量,并且在泛型类型上做的工作并不很好,这里的其他人指出了如何处理实际的方法签名,但是没有移植该C ++代码,我会重新设计一些更适合C#风格的东西。

摆脱全局变量。

我的C ++非常生锈,但是看起来您正在从流中读取值类型。

您可以将泛型限制为引用类型或值类型,并且可以使用default关键字初始化一个空变量。

public T Read<T>( Stream input ) 
    where T:struct //forces T to be a value type
{
    T returnValue = default(T); //init a return value
    int index = input.Position;

    //your conversion here

    return returnValue;
}

您最好也将流作为参数传递。

还请记住,在C ++中,这些是模板-您将获得为每种使用的类型编译的代码的副本。 这排除了从C#引用C ++库的可能性,因为在编译C ++时,它不一定具有C#代码要求编译的类型。

在C#中,仅编译了一个类,并且可以在外部引用它。

我不确定您的数据流来自何处。 但是,如果它是非托管指针,则可以执行以下操作。

public static T Read<T>(ref IntPtr ptr) 
  where T : struct {
  var size = Marshal.SizeOf(typeof(T));
  var value = (T)Marshal.PtrToStructure(ptr, typeof(T));
  ptr = new IntPtr(ptr.ToInt64() + size);
  return value;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM