我在List中有一些对象,比方说List<MyClass>,MyClass有几个属性.我想基于MyClass的3个属性创建列表的索引.在这种情况下,2个属性是int,而一个属性是datetime.
基本上我希望能够做到这样的事情:
Dictionary< CompositeKey , MyClass > MyClassListIndex = Dictionary< CompositeKey , MyClass >();
//Populate dictionary with items from the List<MyClass> MyClassList
MyClass aMyClass = Dicitonary[(keyTripletHere)];
Run Code Online (Sandbox Code Playgroud)
我有时会在列表上创建多个字典来索引它所拥有的类的不同属性.我不知道如何最好地处理复合键.我考虑过对三个值进行校验和,但这会产生碰撞的风险.
我研究了性能下降并将其跟踪以减缓HashSets的速度.
我有可用值作为主键的结构.例如:
public struct NullableLongWrapper
{
private readonly long? _value;
public NullableLongWrapper(long? value)
{
_value = value;
}
}
Run Code Online (Sandbox Code Playgroud)
我注意到创建一个HashSet<NullableLongWrapper>异常缓慢.
以下是使用BenchmarkDotNet的示例:( Install-Package BenchmarkDotNet)
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
public class Program
{
static void Main()
{
BenchmarkRunner.Run<HashSets>();
}
}
public class Config : ManualConfig
{
public Config()
{
Add(Job.Dry.WithWarmupCount(1).WithLaunchCount(3).WithTargetCount(20));
}
}
public struct NullableLongWrapper
{
private readonly long? _value;
public NullableLongWrapper(long? value)
{
_value = value;
}
public …Run Code Online (Sandbox Code Playgroud) 我创建了两个TheKey类型为k1 = {17,1375984}和k2 = {17,1593144}的结构.显而易见,第二个字段中的指针是不同的.但两者都得到相同的哈希码= 346948941.预计会看到不同的哈希码.请参阅下面的代码.
struct TheKey
{
public int id;
public string Name;
public TheKey(int id, string name)
{
this.id = id;
Name = name;
}
}
static void Main() {
// assign two different strings to avoid interning
var k1 = new TheKey(17, "abc");
var k2 = new TheKey(17, new string(new[] { 'a', 'b', 'c' }));
Dump(k1); // prints the layout of a structure
Dump(k2);
Console.WriteLine("hash1={0}", k1.GetHashCode());
Console.WriteLine("hash2={0}", k2.GetHashCode());
}
unsafe static void Dump<T>(T s) …Run Code Online (Sandbox Code Playgroud) 可能重复:
C#为什么相等的小数会产生不相等的哈希值?
我在我的.NET 3.5应用程序(x86或x64,我试过两个)中遇到了一个问题,其中具有不同数量的尾随零的小数具有不同的哈希码.例如:
decimal x = 3575.000000000000000000M;
decimal y = 3575.0000000000000000000M;
Console.WriteLine(x.GetHashCode());
Console.WriteLine(y.GetHashCode());
Console.WriteLine(x == y);
Console.WriteLine(x.GetHashCode() == y.GetHashCode());
Run Code Online (Sandbox Code Playgroud)
在我的机器上输出以下内容:
1085009409
1085009408
True
False
Run Code Online (Sandbox Code Playgroud)
我认为哈希码的差异是由不同比例因子引起的两个数字的不同内部表示.
虽然我可以通过删除尾随零来解决这个问题,但我总是假设GetHashCode应该为x和y返回相同的值,如果x == y.这个假设是错误的,还是Decimal.GetHashCode的问题?
编辑:要清楚我正在使用Visual Studio 2008 SP1,.NET 3.5的版本.
为了寻找词典的快速复合键,我遇到异常,我无法理解也无法证明.
在有限的测试中
Dictionary<KeyValuePair<UInt32, UInt32>, string>
Run Code Online (Sandbox Code Playgroud)
明显慢于(200:1)
Dictionary<KeyValuePair<UInt16, UInt16>, string>
Run Code Online (Sandbox Code Playgroud)
测试两个循环,从0到1000 Populate,然后包含ContainsKey
Poplulate ContainsKey
UInt32 92085 86578
UInt16 2201 431
Run Code Online (Sandbox Code Playgroud)
问题是
new KeyValuePair<UInt32, UInt32>(i, j).GetHashCode();
Run Code Online (Sandbox Code Playgroud)
产生许多重复.
在循环i和j 1024中,仅创建1024个唯一散列值.
基于来自CasperOne的雪崩评论尝试了i*31和j*97(两个素数),这导致105280在1024X1024上独一无二.仍然有很多重复.CasperOne我知道这与随机不一样.但随机输入并不是我的工作.GetHashCode()应该随机化输出.
为什么重复次数很多?
相同的循环
new KeyValuePair<UInt16, UInt16>(i, j).GetHashCode();
Run Code Online (Sandbox Code Playgroud)
产生1024 X 1024唯一哈希码(完美).
Int32有同样的问题.
这些重复哈希值会终止
Dictionary<KeyValuePair<UInt32, UInt32>, string>
Run Code Online (Sandbox Code Playgroud)
与Int16相比,元组还会生成很多重复项,在Int32中不会降级.
生成原始KVP和原始KPV.GetHashCode的时间类似.
与HashSet相同的异常.
Dictionary<KeyValuePair<UInt32, UInt32>, string> dKVPu32 = new Dictionary<KeyValuePair<UInt32, UInt32>, string>();
Dictionary<KeyValuePair<UInt16, UInt16>, string> dKVPu16 = new Dictionary<KeyValuePair<UInt16, UInt16>, string>();
KeyValuePair<UInt32, UInt32> kvpUint32;
KeyValuePair<UInt16, UInt16> kvpUint16;
int range = 1000;
Int32 hashCode;
HashSet<Int32> kvpUint32Hash = new HashSet<Int32>(); …Run Code Online (Sandbox Code Playgroud) 我搜索正确组合成分哈希码的帮助器GetHashCode()似乎带来了一些敌意.我从评论中得到的印象是,一些C#开发人员认为你不应该GetHashCode()经常覆盖- 当然一些评论者似乎认为帮助正确行为的图书馆将毫无用处.这种功能在Java中被认为是有用的,Java 社区要求将它添加到JDK中,现在它已经在JDK 7中了.
是否有一些基本原因在C#中你不需要 - 或者绝对不应 - 像Java一样频繁地覆盖GetHashCode()(并相应地Equals())?我发现自己经常使用Java来做这件事,例如,每当我创建一个我知道要保留的类型HashSet或者用作HashMap(等同于.net Dictionary)中的键时.
帮助说:
匿名类型是直接从对象派生的类类型,不能转换为除object之外的任何类型.尽管您的应用程序无法访问它,但编译器为每个匿名类型提供了一个名称.从公共语言运行库的角度来看,匿名类型与任何其他引用类型没有区别.
如果程序集中的两个或多个匿名对象初始值设定项指定了具有相同顺序且具有相同名称和类型的属性序列,则编译器会将对象视为相同类型的实例.它们共享相同的编译器生成的类型信息.
因为匿名类型上的Equals和GetHashCode方法是根据属性的Equals和GetHashCode方法定义的,所以同一匿名类型的两个实例只有在它们的所有属性相等时才相等.
这些都是真的,但是怎么样?参考源明确显示了如何比较对象(ReferenceEquals)和"直接从对象派生"的类型不能具有此特殊行为.它不匹配的水煤浆Equals在ValueType任.
那怎么办?匿名类型如何覆盖Equals()并且GetHashCode()没有任何可见的覆盖?
我正在研究一个从文本文件中读取数百万个浮点数的程序.这个程序在我正在设计的游戏中运行,所以我需要它快速(我正在加载一个obj文件).到目前为止,由于Convert.ToSingle()的速度较慢,加载一个相对较小的文件大约需要一分钟(没有预编译).有更快的方法吗?
编辑:这是我用来解析Obj文件的代码
using System;
using System.IO;
using System.Collections.Generic;
using OpenTK.Math;
using System.Drawing;
using PlatformLib;
public class ObjMeshLoader
{
public static StreamReader[] LoadMeshes(string fileName)
{
StreamReader mreader = new StreamReader(PlatformLib.Platform.openFile(fileName));
MemoryStream current = null;
List<MemoryStream> mstreams = new List<MemoryStream>();
StreamWriter mwriter = null;
if (!mreader.ReadLine().Contains("#"))
{
mreader.BaseStream.Close();
throw new Exception("Invalid header");
}
while (!mreader.EndOfStream)
{
string cmd = mreader.ReadLine();
string line = cmd;
line = line.Trim(splitCharacters);
line = line.Replace(" ", " ");
string[] parameters = line.Split(splitCharacters);
if (parameters[0] == "mtllib") …Run Code Online (Sandbox Code Playgroud) 我有一段时间以来一直使用的WPF DataGrid,效果很好.与其他海报不同,我还没有滚动条或鼠标滚轮的问题.我已CTRLEND编程到DataGrid的末尾,然后它跟踪最近添加的项目.我可以DataGrid用up键向上滚动内容.
但是,我对down键的行为非常奇怪!如果我从我的顶部开始DataGrid并按住down键,它会滚动一点,然后最终在两个相邻行之间来回反弹.如果我pgdn,它将向下滚动更多,然后跳回到前两行的最顶部,它将跳转到之间,然后向下滚动到我要去的点pgdn.如果我再向下翻页,该down键将滚动到结尾.如果我走到顶部DataGrid并重新开始,我会一遍又一遍地得到完全相同的行为.
我还没有找到解决这个问题的帖子,而且我在DataGrid文档中没有看到任何有用的内容.
它只是一个三列DataGrid,每列显示TextBlocks.任何人都可以解释为什么这种滚动模式有问题吗?这是XAML:
<DataGrid ItemsSource="{Binding MainLog}" AutoGenerateColumns="False"
Name="log_datagrid" SelectedCellsChanged="log_datagrid_SelectedCellsChanged"
KeyUp="datagrid_KeyUp" LoadingRow="log_datagrid_LoadingRow">
<DataGrid.Columns>
<!-- timestamp -->
<DataGridTemplateColumn Header="Timestamp">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Timestamp}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- level -->
<DataGridTemplateColumn Header="Level">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Level}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- error message -->
<DataGridTemplateColumn Header="Message">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Message}" …Run Code Online (Sandbox Code Playgroud) c# ×9
.net ×4
dictionary ×3
gethashcode ×2
hash ×2
struct ×2
.net-4.0 ×1
datagrid ×1
equals ×1
java ×1
mono ×1
opengl ×1
opentk ×1
performance ×1
wpf ×1
wpfdatagrid ×1