2009-04-19 10 views
1

私はジェネリックスに新しく、C#で見つかることができるのはList [T]です。それ以外は何もありません。C#:タイプの汎用メソッド(byte/word/dword)の作成方法は?

これは私がその

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

質問のように呼ばれる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; 
} 

その

で変換する必要がC++コード:どのようにC#ジェネリックであることを行うには?

+0

"... C++コードはC#で翻訳する必要があります"なぜですか? C#の既存のC++コードをさまざまな方法で呼び出すことができます。テンプレートを使用しているので、おそらくC++/CLIはこの特定のケースにとって最も簡単な方法です。 –

答えて

4

あなたのコードは、BinaryReaderクラスのReadInt16,ReadInt32およびReadInt64のメソッドを模倣しているようです。

グローバル変数に関する知識がなくても書き換えを提供するのは難しいです。ストリームがバイト配列であると仮定すると、次のコードが機能します。

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]; 
} 
+0

ニースの解決策(+1)。 'where T:struct'の制限を追加します。これは参照型に対して呼び出すことはできません。 – Keith

1

あなたが探しているもののためのシグネチャは次のとおりです。

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

あなたは型にこれを配置する必要があります。インスタンスまたは静的メンバーにすることができます。


編集:あなたが明示的にジェネリック型引数を渡す必要が除い

それは、他の方法と同じように使用されます。例:

byte mode = Reader.Read<byte>() 
+1

いくつかの使用例も素晴らしいでしょうか? –

+0

私は、Readerクラスで何か「返す」方法を知りたいと思います。例を挙げてください。 –

4

これは関数テンプレートです。 C#でクラスが必要ですが、次のようなものが必要です。

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

おそらく、値型に制限するなど、制約を使用したいと思うでしょう。

あなたはこのように関数を呼び出すことができます。

Utility.Read<int>(); 
+0

それはどのように呼ばれていますか? –

1

C++の例はグローバル変数でいっぱいであり、ジェネリック型ではうまくいかないことを指摘したいだけですが、実際のメソッドシグネチャの処理方法を説明していますが、そのC++コードを移植する代わりに、C#のスタイルに合ったものを作り直すことにしました。

グローバルを削除します。

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#ではコンパイルされたクラスは1つしかなく、外部から参照できます。

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; 
} 
関連する問題