1)構造体は値によって渡されています。メソッドのフィールドの値を変更した場合、渡された元の構造体では更新されません。変更された構造体を返すか、refパラメータとして宣言する必要があります。
2)ボクシングはパフォーマンスはあまり良くありませんが、それほど悪くはありません。しかし、重要なことは、(私が見つけたものから)働くために反射を使って値を設定するためにボクシングを使う必要があるということです。 FieldInfo.SetValue(object、object)は、オブジェクトをパラメータとして取り、構造体を囲み、ボックス化された構造体の値を設定しますが、元の構造体は更新されません。
結果:
a: StructA[S1=0x1122, I1=0x11223344]
a: StructA[S1=0x2211, I1=0x44332211]
ここで動作するコードです:
class Test
{
public static void Convert<T>(ref T arg)
{
object o = arg; // box so SetValue will work
Type argType = arg.GetType();
foreach (FieldInfo fi in argType.GetFields())
{
if (fi.FieldType == typeof(System.Int32))
fi.SetValue(o, IPAddress.HostToNetworkOrder((int)fi.GetValue(o)));
else if (fi.FieldType == typeof(System.Int16))
fi.SetValue(o, IPAddress.HostToNetworkOrder((short)fi.GetValue(o)));
}
arg = (T)o; // unbox and set value of ref parameter
}
public static void RunTest()
{
StructA a = new StructA() { I1 = 0x11223344, S1 = 0x1122 };
Console.WriteLine("a: {0}", a);
Convert(ref a);
Console.WriteLine("a: {0}", a);
}
}
public struct StructA
{
public short S1;
public int I1;
public override string ToString()
{
return string.Format("StructA[S1=0x{0:X4}, I1=0x{1:X8}]", S1, I1);
}
}
public struct StructB
{
public short S2;
public int I2;
public override string ToString()
{
return string.Format("StructB[S2=0x{0:X4}, I2=0x{1:X8}]", S2, I2);
}
}
あなたはまた、それはあなたの状況に適用された場合にのみ、構造体(値型)を許可するようにTを制約することができます - toNetworkByte(T引数)where T:struct –
jeffora
@jeffora:あなたは確かにすることができます。残念ながら、ジェネリックメソッドに*特定の* struct型だけを受け入れるように制約する方法はないので、私はそれについて言及していませんでした。私は私の答えを更新します。 –
もちろん。それは特定の構造体の場合にのみ一般的ではありません;-) – jeffora