我是仿制药的新手,我在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#Generics做到这一点?
答案 0 :(得分:4)
这是一个功能模板。你需要一个C#类,但是像:
public static class Utility
{
public static Type Read<Type>()
{
//Converted code to c# that returns a Type;
}
}
您可能希望对此使用约束,例如限制值类型。
你可以这样调用这个函数:
Utility.Read<int>();
答案 1 :(得分:4)
您的代码似乎模仿ReadInt16类的ReadInt32,ReadInt64和BinaryReader方法。
如果不了解全局变量,很难提供重写。假设流是一个字节数组,以下代码将起作用。
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];
}
答案 2 :(得分:1)
您正在寻找的签名是:
public class Reader
{
public static T Read<T>()
{
}
}
您需要将其放入一个类型中。它可以是实例或静态成员。
编辑:
除了必须显式传递泛型类型参数外,它的使用方式与其他方法类似。例如:
byte mode = Reader.Read<byte>()
答案 3 :(得分:1)
查看MSDN上的Introduction to C# Generics文章。之后应该是不言自明的......
答案 4 :(得分:1)
我只是想指出你的C ++示例充满了全局变量,并且做了一些在泛型类型中不能很好地工作的东西,其他人已经指出了如何处理实际的方法签名,而不是移植那个C ++代码,我会更好地修改一些符合C#风格的东西。
摆脱全局变种。
答案 5 :(得分:0)
我的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#中只编译了一个类,可以在外部引用它。
答案 6 :(得分:0)
我不完全确定您的数据流来自哪里。但是,如果它是一个非托管指针,您可以执行以下操作。
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;
}