各种方面的,角度越独特越好。struct StructA
{
public string s;
public int i;
}struct StructB
{
public int i;
public string s;
}[1]结构名不一样,
[2]字段顺序不一样还会产生哪些重要大差别~~
{
public string s;
public int i;
}struct StructB
{
public int i;
public string s;
}[1]结构名不一样,
[2]字段顺序不一样还会产生哪些重要大差别~~
解决方案 »
- 设置的窗体图标.ico可以改大小吗?
- Socket SocketFlags 标识符的意思
- spread 导出Excel文件如何将表头也导出?
- “System.Data.DataRow.DataRow(System.Data.DataRowBuilder)”不可访问,因为它受保护级别限制??
- 求救:如何屏蔽子网页的弹出窗口?
- 俺是小虾,写个数组操作吧,有问题了,求助????
- 关于输入输出文件的代码
- 从datagrid中提取值,插入数据库出错,谁能帮忙看下,哪错了
- C#进行填表,实现图片上传功能
- 关于在dataGridView中对Cell赋值的问题!
- regasm注册的问题,请大家帮忙下
- OleDb取数据
using System;
using System.Runtime.InteropServices;struct StructA
{
public string s;
public int i;
}struct StructB
{
public int i;
public string s;
}class Program
{
static void Main()
{
Console.WriteLine(Marshal.SizeOf(typeof(StructA))); // 输出:8
Console.WriteLine(Marshal.SizeOf(typeof(StructB))); // 输出:8
}
}
一定有不一样的地方,才提出来大家研究。
一般情况下,我是不会无聊到那种程度。灵感来自于以下这个贴子:
http://topic.csdn.net/u/20090823/21/032c6587-ff8a-4d97-858f-73b752b6ca22.html?seed=1269055200&r=59295990#r_59295990我先公布一下其中一个方案的答案:
就是这两种写法会直接影响到该结构体的hashcode值,注意以下两点:
[1]落是在结构体上
[2]取值和效率都不同,取决于使用该结构的场景。建议先看一下,Effective C#热一下身,还会引出很多其它的问题:
《Effective C#》Item 10:小心GetHashCode函数所存在的陷阱
就“问题”而研究“问题”,
用“代码”说话...
-------------------------
哇,空军 你有fans了
Console.WriteLine(new StructA() { s = "a", i = 2 }.GetHashCode());
Console.WriteLine(new StructA() { s = "a", i = 3 }.GetHashCode());
Console.WriteLine(new StructA() { s = "b", i = 3 }.GetHashCode());
Console.WriteLine(new StructA() { s = "c", i = 3 }.GetHashCode());
猜想 class/struct 的默认 hashcode 是根据第一个字段成员来计算的。不过应该注意的是,如果你的 struct/class 要做为 hash/dictionary 的 key,或者要进行等式比较,一定要实现自己的操作符 == 和 !=,还有两个重载两个方法 GetHashCode 和 EqualTo,默认实现的 GetHashCode 是不可靠的。
呵呵,说句实在话,我也常见得讨论这个问题没什么意义自定义 struct 本来就不可以把 GetHashCode 直接拿来用的。
http://topic.csdn.net/u/20090824/22/72a8a4fe-53d2-4ee5-8715-a66f72ff9b29.html?seed=461134921&r=59308175#r_59308175
=========
整理如下:
=========
一个理想化的hashcode函数三原则(注意:理想的)
[1]唯一性原则
两个相等的对象,通过GetHashCode函数产生的结果要相等,
否则,通过其产生HashCode而存入HashTable中的数据就无法取出来了。
[2]不变性原则
对于一个类型的对象来说,其GetHashCode函数的返回值要自始至终要保持一致。
否则,通过其产生HashCode而存入HashTable中的数据就无法取出来了。
[3]高效率原则
在GetHashCode函数中需要提供一个比较好的哈希函数,
也就是在最小的范围内来实现数据分散,
换句话说它的离散度决定HashTable存取效率。系统默认提供的hashcode实现
[1]引用类型(GetHashCode函数)
特点:基本是正确的,效率不高的
流程:
一个.Net程序在运行的时候会对引用类型的对象进行标记,大致操作类似如下:
标记起始为0,当创建一个引用类型对象的时候,这个标记会自动加一,
对象释放后标记并不做减一操作,这有点儿像数据库中的自增字段。
[2]结构类型(GetHashCode函数)
特点:基本是错误的,一般情况下效率不高的
值类型自带的GetHashCode是以其第一个成员的GetHashCode值作为其的返回值。匹配原则:
重写了Equals函数,一定要重写GetHashCode函数来达到一致.
(否则会警告,但不会出错,在下个回贴中结合代码说明)重写注意事项:(参照35楼给出的例子)
[1]不管是值类型还是引用类型,要保证产生HashCode的成员不能被修改;
[2]对于产生HashCode的成员修改,要以产生新对象进行处理,同时要在使用端作相应的修改,即先删除旧的在添加新的。如何产生高效的hashcode
[1]这个以前看过,忘了,下次补上,(数学+数学+素数)
[2]^(异或)+<<>>(移位操作),常用手段(见下贴给同了的例子)
[3]最重要的是具体情况具体分析,在有条件的情况上尽可能满足上面的:<一个理想化的hashcode函数三原则>
实现IEqualityComparer<string>接口,
Equals/GetHashCode成对处理
这两个实现方法是我们关注的重点[2]数据生成部分
这里借用一下superdullwolf提供的案例
最值得回味的地方在于,要求中改变了"相等"的含度:
[abc]=[cba]!=[abd]
这样GetHashCode就有了演译的舞台[3]生成部分
int count = myArr.Distinct(comparer).Count();
这里用到了lamada表达式,一句话解决了所有的核心代码
Distinct是其中的扩展方法
public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer);
通过Distinct方法,实现了"等于"规则定义上的解耦[4]对比部分
感谢yuyingying1986提供的代码,用于检验程序的正确性
下面注释的两句代码,用于检查GetHashCode的工作原理,会在下一贴中继续加以说明
//return countGetHashCode;//测试countGetHashCode全不冲突时,Equals的依赖情况
//return 0x7FFFFFFF;//测试countGetHashCode全冲突时,Equals的依赖情况#define pcnetman888
#define yuyingying1986using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;public class Comparer : IEqualityComparer<string>
{
public int countEquals = 0;
public int countGetHashCode = 0; public bool Equals(string x, string y)
{
//int hashcodeX = this.GetHashCode(x);
//int hashcodeY = this.GetHashCode(y); //if (hashcodeX != hashcodeY) return false; countEquals++; char[] charArrX = x.ToCharArray();
Array.Sort(charArrX);
string stringX = new string(charArrX); char[] charArrY = y.ToCharArray();
Array.Sort(charArrY);
string stringY = new string(charArrY); //bool result = ((new string(charArrX)) == (new string(charArrY)));
bool result = (stringX == stringY); if (result)
{
//Console.WriteLine("x:{0},y:{1}", stringX, stringY);
return true;
}
else
{
return false;
}
} public int GetHashCode(string x)
{
countGetHashCode++;
int hashcode = 0; //return countGetHashCode;//测试countGetHashCode全不冲突时,Equals的依赖情况
//return 0x7FFFFFFF;//测试countGetHashCode全冲突时,Equals的依赖情况 char[] charArrX = x.ToCharArray();
Array.Sort(charArrX); int count = charArrX.Count();
for (int i = 0; i < count; i++)
{
hashcode ^= ((int)charArrX[i]) << (count - i - 1);
} return hashcode & 0x7FFFFFFF;
}
}class Test
{
static void Main(string[] args)
{
//10万个字符串。
int totalStr = 5 * 1000;
List<string> myArr = new List<string>();
int totalLength = 0;
char[] input = "白日依山尽黄河入海流欲穷千里目更上一层楼危楼高百尺可以摘星辰不感高声语恐惊天上人".ToCharArray();
Random rand = new Random();
for (int i = 0; i < totalStr; i++)//10万个数据
{
string tempStr = "";
int tempLength = rand.Next(3, 16); //3到16个字符
for (int j = 0; j < tempLength; j++)
{
tempStr += input[rand.Next(0, input.Length)];//用a-z英文测试
}
totalLength += tempLength;
myArr.Add(tempStr);
} //测试开始
long begin = System.DateTime.Now.Ticks;
//这里写程序代码,可以写函数或类什么的在此调用。#if pcnetman888
//=====================================================
Comparer comparer = new Comparer();
int count = myArr.Distinct(comparer).Count();
Console.WriteLine("共" + count + "条不重复数据");
Console.WriteLine("GetHashCode:调用{0}次,Equals:调用:{0}次!",comparer.countGetHashCode,comparer.countEquals);
//=====================================================
#endif#if yuyingying1986
//=====================================================
Hashtable hshTable = new Hashtable(); foreach (string item in myArr)
{
char[] charArr = item.ToCharArray();
Array.Sort(charArr);
string sKey = new string(charArr);
if (hshTable.Contains(sKey))
continue;
else
hshTable.Add(sKey, item);
} Console.WriteLine("共" + hshTable.Count + "条不重复数据");
//=====================================================
#endif long end = System.DateTime.Now.Ticks;
Console.WriteLine("总共" + totalStr / 10000 + "万个数据,总长度" + totalLength + ",做完需要" + System.TimeSpan.FromTicks(end - begin).Milliseconds + "毫秒");
Console.ReadLine();
}
}
http://topic.csdn.net/u/20090823/21/032c6587-ff8a-4d97-858f-73b752b6ca22.html
其中的第62楼和63楼(代码太长,一个回贴发不了)有一个问题实在想不通。GetHashCode确实能够短路掉Equals,
但是Equals还是被调用了,
难道编译器做了手脚。 请求支援,查不到次料,请坛子里的高手帮个忙.~~~
真正能成才的技术人员就要从最低做起!选择一个好的起点很重要!
看是做Java工作的时候只接触struts+jsp 而且做得小型企业网!说是安全! 熟不知自己的门户网站用Java做得还经常被攻击!狗屁的安全啊!
现在是什么时代,互联网信息时代!安全随重要,但更重要的是时机,抓住时机把网站推出去就是胜者!
所以我看是学习asp.net php 虽然不可能精通,但我明白,不管用什么语言,要是掌握了编程思想就OK了!
只要经历过编程的人就会明白,不能只是听经理规定你做什么就做什么,要学会经理是怎么做的!
那样我们才会成为经理!
学习编程的朋友 讨论一下呗!
温馨小贴士:http://www.eluyouni.com 七夕网 E路有你
hashcode关没有要求一对一,也不可能,只是尽量散列,
否则基本上没有多上对象能实现这个了.
http://topic.csdn.net/u/20090825/16/725bc96a-33f9-4c63-85ef-01d22d6c1ed2.html?seed=34499191&r=59362105#r_59362105临时寄存一下:using System;
using System.Collections;
public class List
{
public static IEnumerator Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
static void Main()
{
IEnumerator ie = Power(2, 8);
Console.WriteLine(ie.GetType().ToString()); //ie.Reset();
while (ie.MoveNext())
{
Console.Write("{0} ", ie.Current);
} Console.ReadKey();
}
}
是啊,HashCode 的设计原则不是一对一,正因为如此,才说你用HashCode出解答那道题肯定会有误差。
你没有理解到设计HashCode的真正含义:
HashCode可以看作Equals的辅助,
就是:利用HashCode函数来做预判,来减少Equals的调用次数.
HashCode函数至少要求是"合理的",
"合理的"的含义是能够识别出被比较对象的"逻辑"不等关系.
上面代码的例子中,不等关系不是原"字符串"不等,而是"字符组合后不重复"不等.public int GetHashCode(string x)
{
countGetHashCode++;
int hashcode = 0; //return countGetHashCode;//测试countGetHashCode全不冲突时,Equals的依赖情况
//return 0x7FFFFFFF;//测试countGetHashCode全冲突时,Equals的依赖情况 char[] charArrX = x.ToCharArray();
Array.Sort(charArrX); int count = charArrX.Count();
for (int i = 0; i < count; i++)
{
hashcode ^= ((int)charArrX[i]) << (count - i - 1);
} return hashcode & 0x7FFFFFFF;
}
这段代码,是产生一个尽可能的"逻辑"关系的散列,
虽然不可能做到一对一的关系,(数组大到16的16次方时)
这个效率还是挺高的,在100万时,重码率也不到1%,
在2000~5000之间基本上是一个重码.
http://topic.csdn.net/u/20090825/16/725bc96a-33f9-4c63-85ef-01d22d6c1ed2_3.html211楼、213楼、229楼、230楼、236楼、239楼、247楼、253楼、257楼、258楼。