あなたはどんなゴールを目指していますか?パフォーマンスの場合は、構造体を関数パラメーターとして渡すたびに値によってコピーされるため、クラスを使用する必要があります。
3 つの文字列、12 の小数 (うち 7 は null 可能)、および 4 つの整数。
64 ビット マシンでは、ポインターのサイズは 8 バイトになり、10 進数は 16 バイト、int は 4 バイトになります。パディングを無視すると、構造体はインスタンスごとに 232 バイトを使用します。これは、推奨される最大値である 16 バイトと比較してはるかに大きく、これはパフォーマンス的に理にかなっています (クラスは、そのオブジェクト ヘッダーのために少なくとも 16 バイトを必要とします...)。
値のフィンガープリントが必要な場合は、16 バイトのフィンガープリントを生成する SHA256 などの暗号化グレードのハッシュ アルゴを使用できます。これはまだユニークではありませんが、少なくとも十分にユニークです。しかし、これはかなりのパフォーマンスも犠牲にします。
Edit1:
Java Script Web クライアント キャッシュ内のオブジェクトを識別するためにハッシュ コードが必要であることを明らかにした後、私は混乱しています。サーバーが同じデータを再度送信するのはなぜですか? クライアントがまだ受信していないデータのみを送信するようにサーバーをよりスマートにする方が簡単ではないでしょうか?
あなたの場合、SHAハッシュアルゴリズムは、オブジェクトインスタンスタグを作成するのに問題ありません。
なぜハッシュコードが必要なのですか? メモリ効率の良い方法で値を格納することが目標である場合は、辞書を使用して同一の値を 1 回だけ格納し、検索キーとして int を使用する FooList を作成できます。
using System;
using System.Collections.Generic;
namespace MemoryEfficientFoo
{
class Foo // This is our data structure
{
public int A;
public string B;
public Decimal C;
}
/// <summary>
/// List which does store Foos with much less memory if many values are equal. You can cut memory consumption by factor 3 or if all values
/// are different you consume 5 times as much memory as if you would store them in a plain list! So beware that this trick
/// might not help in your case. Only if many values are repeated it will save memory.
/// </summary>
class FooList : IEnumerable<Foo>
{
Dictionary<int, string> Index2B = new Dictionary<int, string>();
Dictionary<string, int> B2Index = new Dictionary<string, int>();
Dictionary<int, Decimal> Index2C = new Dictionary<int, decimal>();
Dictionary<Decimal,int> C2Index = new Dictionary<decimal,int>();
struct FooIndex
{
public int A;
public int BIndex;
public int CIndex;
}
// List of foos which do contain only the index values to the dictionaries to lookup the data later.
List<FooIndex> FooValues = new List<FooIndex>();
public void Add(Foo foo)
{
int bIndex;
if(!B2Index.TryGetValue(foo.B, out bIndex))
{
bIndex = B2Index.Count;
B2Index[foo.B] = bIndex;
Index2B[bIndex] = foo.B;
}
int cIndex;
if (!C2Index.TryGetValue(foo.C, out cIndex))
{
cIndex = C2Index.Count;
C2Index[foo.C] = cIndex;
Index2C[cIndex] = cIndex;
}
FooIndex idx = new FooIndex
{
A = foo.A,
BIndex = bIndex,
CIndex = cIndex
};
FooValues.Add(idx);
}
public Foo GetAt(int pos)
{
var idx = FooValues[pos];
return new Foo
{
A = idx.A,
B = Index2B[idx.BIndex],
C = Index2C[idx.CIndex]
};
}
public IEnumerator<Foo> GetEnumerator()
{
for (int i = 0; i < FooValues.Count; i++)
{
yield return GetAt(i);
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
class Program
{
static void Main(string[] args)
{
FooList list = new FooList();
List<Foo> fooList = new List<Foo>();
long before = GC.GetTotalMemory(true);
for (int i = 0; i < 1000 * 1000; i++)
{
list
//fooList
.Add(new Foo
{
A = i,
B = "Hi",
C = i
});
}
long after = GC.GetTotalMemory(true);
Console.WriteLine("Did consume {0:N0}bytes", after - before);
}
}
}
同様のメモリ節約リストがここにあります