符合标准的TreeView实现(Div+CSS+JS+ASP.NET)

1 Comment

这几天有点小活,要求是ASP.NET的,虽然我不怎么看好ASP.NET,但是人家要求了我也就照做吧。
最复杂的部分是一个TreeView。出于兼容性和简单性考虑没有用ASP.NET的TreeView控件,而是参考一篇文章自行写了一个出来。

[singlepic=18460]

技术指标如下:

  • 实现:Div+CSS+JavaScript+ASP.NET(C#)
  • 功能:可以实现无限级的TreeNode
  • 标准:在IE 7和Firefox 3.1下显示效果相同,兼容XHTML 1.0 Strict最严格的网页标准

效果如左图所示。最后一个函数可能会因为超宽看不到全部,具体请参照文章附件中的源代码。
附件下载:http://download.nocoo.us/Download/Archive/TreeViewCode.rar

TreeNode.cs

/// <summary>
/// TreeView结点类
/// </summary>
public class TreeNode
{
    private string name;
    private string href;
    private List<TreeNode> subNodes = new List<TreeNode>();

    /// <summary>
    /// 结点名
    /// </summary>
    public string Name { get { return name; } }
    /// <summary>
    /// 结点链接
    /// </summary>
    public string Href { get { return href; } }
    /// <summary>
    /// 下级结点个数
    /// </summary>
    public int Count { get { return this.subNodes.Count; } }
    /// <summary>
    /// 获取或者设置下级结点
    /// </summary>
    /// <param name="index">序号</param>
    /// <returns>下级结点</returns>
    public TreeNode this[int index]
    {
        get { return subNodes[index]; }
        set { subNodes[index] = value; }
    }

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="name">结点名</param>
    public TreeNode(string name)
    {
        this.name = name;
        this.href = null;
    }

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="name">结点名</param>
    /// /// <param name="href">结点链接</param>
    public TreeNode(string name, string href)
    {
        this.name = name;
        this.href = href;
    }

    /// <summary>
    /// 添加下级结点
    /// </summary>
    /// <param name="node">新结点</param>
    public void Add(TreeNode node)
    {
        subNodes.Add(node);
    }
}

TreeView.cs

/// <summary>
/// TreeView
/// </summary>
public class TreeView
{
    private List<TreeNode> nodes = new List<TreeNode>();

    /// <summary>
    /// 填充测试用数据
    /// </summary>
    public void FillTestData()
    {
        TreeNode node1 = new TreeNode("中国", "#");
        TreeNode node11 = new TreeNode("华北地区", "#");
        TreeNode node111 = new TreeNode("河南省", "#");
        TreeNode node112 = new TreeNode("河北省", "#");
        TreeNode node113 = new TreeNode("山东省", "#");
        TreeNode node1131 = new TreeNode("青岛市", "#");
        TreeNode node1132 = new TreeNode("济南市", "#");
        TreeNode node11321 = new TreeNode("市中区", "#");
        TreeNode node11322 = new TreeNode("历下区", "#");
        TreeNode node11323 = new TreeNode("槐荫区", "#");
        TreeNode node11324 = new TreeNode("天桥区", "#");
        TreeNode node11325 = new TreeNode("长清区", "#");
        TreeNode node1133 = new TreeNode("菏泽市", "#");
        TreeNode node1134 = new TreeNode("济宁市", "#");
        TreeNode node1135 = new TreeNode("德州市", "#");
        TreeNode node12 = new TreeNode("东北地区", "#");
        TreeNode node13 = new TreeNode("西北地区", "#");
        TreeNode node14 = new TreeNode("华东地区", "#");
        TreeNode node15 = new TreeNode("西南地区", "#");
        TreeNode node16 = new TreeNode("华南地区", "#");
        TreeNode node17 = new TreeNode("华中地区", "#");
        TreeNode node18 = new TreeNode("港澳台地区", "#");

        node1132.Add(node11321);
        node1132.Add(node11322);
        node1132.Add(node11323);
        node1132.Add(node11324);
        node1132.Add(node11325);

        node113.Add(node1131);
        node113.Add(node1132);
        node113.Add(node1133);
        node113.Add(node1134);
        node113.Add(node1135);

        node11.Add(node111);
        node11.Add(node112);
        node11.Add(node113);

        node1.Add(node11);
        node1.Add(node12);
        node1.Add(node13);
        node1.Add(node14);
        node1.Add(node15);
        node1.Add(node16);
        node1.Add(node17);
        node1.Add(node18);

        nodes.Add(node1);
        nodes.Add(new TreeNode("俄罗斯", ""));
        nodes.Add(new TreeNode("美国"));
        nodes.Add(new TreeNode("韩国"));
        nodes.Add(new TreeNode("澳大利亚"));
        nodes.Add(new TreeNode("印度", ""));
        nodes.Add(new TreeNode("加拿大", ""));
    }

    /// <summary>
    /// 获取TreeView的html代码
    /// </summary>
    /// <returns></returns>
    public string GetHtmlString()
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("<ul>");
        for (int i = 0; i < nodes.Count; i++)
        {
            sb.AppendLine(GetNodeHtml(nodes[i], 1, (i + 1).ToString()));
        }
        sb.AppendLine("</ul>");
        return sb.ToString();
    }

    private string GetNodeHtml(TreeNode thisNode, int depth, string id)
    {
        StringBuilder sb = new StringBuilder();
        bool hasSub = (thisNode.Count > 0) ? true : false;
        sb.AppendLine(string.Format("<li id=\"depth_{0}_item_{1}\">", depth, id));
        sb.AppendLine(string.Format(
            "<div class=\"{0}\" id=\"depth_{1}_item_{2}_ico\" onclick=\"controlNode(this,'depth_{1}_item_{2}')\"></div><h1>{3}</h1>",
            hasSub ? "closedir" : "nodir",
            depth,
            id,
            (thisNode.Href == null || thisNode.Href.Equals("")) ? thisNode.Name : string.Format("<a href=\"{0}\">{1}</a>", thisNode.Href, thisNode.Name)
            ));
        if (hasSub)
        {
            sb.AppendLine(string.Format("<div id=\"depth_{0}_item_{1}_layer\" style=\"display:block;\">", depth, id));
            sb.AppendLine("<ul>");
            for (int i = 0; i < thisNode.Count; i++)
            {
                sb.AppendLine(GetNodeHtml(thisNode[i], depth + 1, string.Format("{0}_{1}", id, i + 1)));
            }
            sb.AppendLine("</ul>");
            sb.AppendLine("</div>");
        }
        sb.AppendLine("</li>");
        return sb.ToString();
    }
}

ASP.NET页面调用:

<%
    CMC.TreeView list = new CMC.TreeView();
    list.FillTestData();
    Response.Write(list.GetHtmlString());
%>

ASP.NET页面JavaScript:

defaultNodeState();

function defaultNodeState()
{
	var nodeState = getCookie("nodeState");
	if(nodeState == null)
	{
	    nodeState = ",|,|,";
		setCookie("nodeState",nodeState);
	}
	var layer = nodeState.split('|');
	for(var i=0;i<layer.length;i++)
	{
		if(layer[i] != ",")
		{
			var lItem = layer[i].split(',');
			var nodeIco = document.getElementById(lItem[0]+"_ico");
			var nodeLayer = document.getElementById(lItem[0]+"_layer");
			OpenNode(nodeIco);
			ShowDiv(nodeLayer);
		}
	}
}
function controlNode(obj,layerId)
{
	var className = obj.className.toLowerCase();
	var layer = document.getElementById(layerId + "_layer");

	cookiesNode(layerId, className);
	if(className == "opendir")
	{
		HideDiv(layer);
		obj.className = "closedir";
	}
	else if (className == "closedir")
	{
		ShowDiv(layer);
		obj.className = "opendir";
	}
}

function cookiesNode(layerId,className)
{
    var nodeState = getCookie("nodeState");
	if(nodeState == null)
	{
	    nodeState = ",|,|,";
		setCookie("nodeState",nodeState);
	}
	var layer = nodeState.split('|');
	var lDepth = getDepth(layerId);
	if(className == "opendir")
	{

		layer[lDepth-1] = ","
	}
	else
	{
		if(layer[lDepth-1] &amp;&amp;amp layer[lDepth-1] != ",") {
                        var lItem = layer[lDepth - 1].split(',');
			var lIco = document.getElementById(lItem[0]+"_ico");
			var lLayer = document.getElementById(lItem[0] + "_layer");
			HideDiv(lLayer);
			CloseNode(lIco);
			    }
			    layer[lDepth - 1] = layerId + "," + lDepth;
		    }
	var cValue = layer[0];
	for(var i=1;i<layer.length;i++)
	{
		cValue += "|" + layer[i];
	}
	setCookie("nodeState",cValue);
}

function getDepth(layerId)
{
	var lItem = layerId.split('_');
	return lItem[1];
}

function OpenNode(obj)
{
	obj.className = "opendir";
}
function CloseNode(obj)
{
	obj.className = "closedir";
}
function HideDiv(obj)
{
    obj.style.display='none';

}
function ShowDiv(obj)
{
    obj.style.display='block';
}

//设置cookies
function setCookie(name,value)
{
    var Days = 30;
    var exp = new Date();
    exp.setTime(exp.getTime() + Days*24*60*60*1000);
    document.cookie = name + "=" + escape(value) +
      ";expires=" + exp.toGMTString();
}
//读取cookies
function getCookie(name)
{
    var arr,reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
    if(arr = document.cookie.match(reg)) return unescape(arr[2]);
    else return null;
}

C++中的Hello World

1 Comment

我一直觉得孔乙己会做一个很好的HR。
“读过书,……我便考你一考。茴香豆的茴字,怎样写的?” ——孔乙己

在初学一门编程语言的时候,写一个“Hello world!”程序是最常见的入门方法。通过写一个成功的“Hello world!”,可以实践这门语言最基本的语法特性,还可以带给自己成就感,真是一举两得。C/C++语言本身有很多特性,如果能够将这些技术分解出来变成一个个的“Hello world!”,并且将这些技术点到为止,貌似也算是一件善事。这里,列举了10个“Hello world!”程序,大家雅俗共赏一下。

1. 最经典的“Hello world!”

“Hello world!”最经典的写法当然是直接用 printf 输出“Hello world!”这几个字符了。无论用C还是 C++,写起来都非常的简洁明了。这里把最常见的几个全部列在下面。

#include <stdio.h>
#include <iostream>

int main()
{
    printf("Hello world!");                   // 教科书的写法
    puts("Hello world!");                     // 我最喜欢的
    puts("Hello" " " "world!");               // 拼接字符串
    std::cout << "Hello world!" << std::endl; // C++风格的教科书写法

    return 0;
}

特别需要注意的是,在C/C++里,如果两个字符串之间除空白符以外没有任何东西,编译器会自动认为这两个字符串是连在一起的字符串。这样,如果一个字符串过长,可以用这种方法换行来写,既不浪费性能,又美观。

2. 用宏写的“Hello world!”

在C/C++里,宏是一个神奇的东西。特别是在C语言中,宏可以帮我们做一些“又脏又累”的活,包括拼接代码片断、隐藏繁琐的实现细节等等。其中特别有趣的是“#”的用法,它可以“提取”参数的名字,把它变成字符串。

#include <stdio.h>

#define Say(sth) puts(#sth)

int main()
{
    return Say(Hello world!);
}

请注意,这个Hello world可是完全没有出现引号哦!

3. 断章取义的“Hello world!”

字符串是一种常量这当然毫无疑问,但是它的类型是什么,这就需要考虑一下了。使用C++的typeid就可以这个问题的答案,而且只要是符合C或C++标准的编译器就应该是一样的结果。比如字符串“Hello world!”,它的类型就是 char const [13]。
知道了这个,就可以写出以下的“Hello world!”:

#include <stdio.h>

int main()
{
    return puts(&amp;"Do not say: Hello world!"[12]);
}

4. 退出时运行的“Hello world!”

大家都知道 main 函数退出意味着程序结束,可是这并不完全正确,我们完全可以在 main 函数退出以后做很多事呢——比如说,输出“Hello world!”。这个功能依赖于C标准库中提供的函数 atexit(),调用这个函数并注册自己的回调函数就行。需要注意,这个函数可以调用多次,最后注册的函数最先执行。

#include <stdio.h>
#include <stdlib.h>

void say()
{
    printf("world!");
}

void sth()
{
    printf("Hello ");
}

int main()
{
    return atexit(say), atexit(sth);
}

5. 读取自己的“Hello world!”

C/C++的编译器提供了一些有用的内置宏,最常用的就是 __FILE__ 和 __LINE__ 了。其中,__FILE__ 代表当前的源文件的文件名,嗯,对了,如果我们让这个程序读取自己的源文件,不就可以做一个很有意思的“Hello world!”了么?

// Hello world!

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::ifstream ifs(__FILE__);
    std::string say, some, word;

    ifs >> say >> some >> word;
    std::cout << some << " " << word;

    return 0;
}

6. 话分两头的“Hello world!”

有了C++的类,我们就可以光明正大的在 main 函数执行之前和之后做感兴趣的事情了。我们可以声明一个全局的类的实例,这样,在 main 函数执行之前会调用这个类的构造函数,结束之后则会调用析构函数。

#include <iostream>

class say
{
public:
    say()
    {
        std::cout << "Hell";
    }

    ~say()
    {
        std::cout << "world!";
    }
}hello;

int main()
{
    std::cout << "o ";
    return 0;
}

7. 传入模板的“Hello world!”

C++的模板功能极为强大,可以说是C++里面最艰深、最经典、最时尚的部分。一个“Hello world!”当然无法使用很多很高级的模板技巧,我也不想只使用模板特化这样无阻挂齿的小技巧,嗯,那就来演示一个比较罕见的用法吧。

#include <iostream>

template <char * words>
class say
{
public:
    void operator () ()
    {
        std::cout << words;
    }
};

extern char hello[] = "Hello world!";

int main()
{
    return say<hello>()(), 0;
}

请注意,这个 extern 是十分必要的,只有加上了 extern,这个指针才是一个编译器间可以确定的值,也才可以参与模板运算。还有,hello 必须为数组类型,而不能为 char*,这个道理和加 extern 是一样的。
此外,这里还演示了 functor 的用法,嗯,关于它的优点就不在这里多说了,反正是与原生指针相比有很多好处就是了。

8. 调用私有函数的“Hello world!”

我们知道,C++类的私有函数是不能被外界访问的,比如说 main 函数里面,它绝对不能访问类的私有函数,除非把它设为类的友元函数。不过我们还是可以用一些比较奇怪的方法访问类的私有函数——当然,这个私有函数必须满足一个条件:它是虚函数。
这里就涉及到一个问题,指向虚函数的虚表放在哪里?对于 VS.Net 2003 而言,虚表是类的第一个成员,虚函数指针按照函数声明的顺序放在虚表里面。当然,这个说法并不严谨,更细节的东西还是去看看那本“成人高钙奶粉”吧,它会给出最权威的解答。
这里是一个很有意思的例子:

#include <iostream>
#include <cstddef>

class secret
{
private:
    virtual void say()
    {
        std::cout << "Hello world!";
    }
};

int main()
{
    secret word;
    (reinterpret_cast<void (*)()>(**(intptr_t**)(&amp;word)))();

    return 0;
}

9. 最暴力的“Hello world!”

最暴力的调用函数的方法是:直接修改函数的返回地址,让这个地址指向我们想要调用的函数。这也就是缓冲区溢出漏洞的应用方法了,不过里面还涉及到很多问题,在这里就不一一列举,想要了解的话,还是去 Google 吧。这里只演示一个可以在 VS.Net 2003 下可以用的“Hello world!”。

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

void say()
{
    puts("Hello world!");
    exit(0);
}

int main()
{
    volatile intptr_t a = 0;
    volatile intptr_t * p = &amp;a;

    *(p + 2) = (intptr_t)say;
    *(p + 3) = (intptr_t)say;

    return 0;
}

10. 外星人说的“Hello world!”

好了,这个“Hello world!”是最匪夷所思的一个了!不过它并没有涉及任何复杂的C/C++语言特性,只是看起来有点酷。你能看懂外星人在说什么不?

#include <stdio.h>

void alien_say(char * p)
{
    while (putchar(*(p += *(p + 1) - *p)));
}

int main()
{
    return alien_say("BETHO! Altec oh liryom(a loadjudas!) dowd."), 0;
}

“C#中反射(Reflection)对const、readonly及static的影响

1 Comment

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace ConsoleApplication1
{
    public class ReflectionTest
    {
        public const int test1 = 1;
        public readonly static int test2 = 1;
        public static int test3 = 1;
        public readonly int test4 = 1;
    }

    class Program
    {
        static void Main(string[] args)
        {
            ReflectionTest t = new ReflectionTest();
            FieldInfo f;

            // const int test1
            // const不应该被更改,猜想应当抛出异常
            // 运行中SetValue(t, 2);确实抛出System.FieldAccessException异常
            Console.WriteLine("test1=" + ReflectionTest.test1);
            f = typeof(ReflectionTest).GetField("test1");
            f.SetValue(t, 2);
            Console.WriteLine("test1=" + ReflectionTest.test1);

            // readonly static int test2
            // 因为readonly不进行编译时检查,编译通过,但是执行时应当出错
            // 但是实际中没有任何提示,也并未更改,错误被吃掉了!
            Console.WriteLine("test2=" + ReflectionTest.test2);
            f = typeof(ReflectionTest).GetField("test2");
            f.SetValue(t, 2);
            Console.WriteLine("test2=" + ReflectionTest.test2);

            // static int test3
            // static变量当然可以通过反射更改
            Console.WriteLine("test3=" + ReflectionTest.test3);
            f = typeof(ReflectionTest).GetField("test3");
            f.SetValue(t, 2);
            Console.WriteLine("test3=" + ReflectionTest.test3);

            // readonly int test4
            // 实例中的readonly变量可以通过反射更改其值
            // 因此,readonly变量的赋值方法总共有三种:
            // 1. 在声明时对readonly变量赋值;
            // 2. 在构造函数中对readonly变量赋值;
            // 3. 使用反射在实例生命期中对readonly变量赋值。
            Console.WriteLine("test4=" + t.test4);
            f = typeof(ReflectionTest).GetField("test4");
            f.SetValue(t, 2);
            Console.WriteLine("test4=" + t.test4);
        }
    }
}

运行结果:

test1=1
未处理的异常:  System.FieldAccessException: 无法设置常量字段。
   在 System.Reflection.MdFieldInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureIn
fo culture)
   在 System.Reflection.FieldInfo.SetValue(Object obj, Object value)
   在 ConsoleApplication1.Program.Main(String[] args) 位置 C:\Documents and Settings\Zheng Li\桌面\ConsoleApplication1\C
onsoleApplication1\Program.cs:行号 28

注释掉第28行的结果:

test1=1
test1=1
test2=1
test2=1
test3=1
test3=2
test4=1
test4=2

标准C++中获取某种数据类型的最大值和最小值

1 Comment

用惯C#,比如我想让一个int数等于无穷大,只需要简单写:

int a = int.MaxValue;

转到C++上,疑惑了…
首先C++不会有属性这种东西,而且不同平台上的某个类型的最大最小值是不一样的。
解决方案是使用limits头文件的方法。

#include <limits>
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    cout<<"short:"<<endl;
    cout<<"min="<<numeric_limits<short>::min()<<endl;
    cout<<"max="<<numeric_limits<short>::max()<<endl;

    cout<<"int:"<<endl;
    cout<<"min="<<numeric_limits<int>::min()<<endl;
    cout<<"max="<<numeric_limits<int>::max()<<endl;

    cout<<"double:"<<endl;
    cout<<"min="<<numeric_limits<double>::min()<<endl;
    cout<<"max="<<numeric_limits<double>::max()<<endl;

    cout<<"long:"<<endl;
    cout<<"min="<<numeric_limits<long>::min()<<endl;
    cout<<"max="<<numeric_limits<long>::max()<<endl;
    return 0;
}

在我的工作站平台(Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1)下输出:

short:
min=-32768
max=32767
int:
min=-2147483648
max=2147483647
double:
min=2.22507e-308
max=1.79769e+308
long:
min=-2147483648
max=2147483647

在Ubuntu Server下用gcc version 4.2.4执行的结果如下

short:
min=-32768
max=32767
int:
min=-2147483648
max=2147483647
double:
min=2.22507e-308
max=1.79769e+308
long:
min=-2147483648
max=2147483647

全周期线性同余随机数生成器

No Comments

全周期线性同余随机数生成器(Full period linear congruential random generator):

[singlepic=18395]

其中如果前两项的和为非负数,则δ(Xi)=0,否则δ(Xi)=1。
研究发现取素数M=2147483647,A=48271可以取得不错的随机性。鉴于这样的取值被仔细研究过并广泛应用,因此一般不要改这两个取值。

算法实现

class RandomFactory
{
public:
	RandomFactory();
	long LinerCongruentialRandom();
private:
	static const long A = 48271;
	static const long M = 2147483647;
	static const long Q = M / A;
	static const long R = M % A;
	long lastValue;
};
#include "stdafx.h"
RandomFactory::RandomFactory()
{
	this->lastValue = 1;
}

long RandomFactory::LinerCongruentialRandom()
{
	long temp = this->A * (this->lastValue % this->Q) -
				R * (this->lastValue / this->Q);
	if(temp < 0)
	{
		temp += this->M;
	}
	this->lastValue = temp;
	return temp % 10;
}

测试代码

RandomFactory *random = new RandomFactory();
int *statistics = new int[10];
for(long i = 0; i < 10; ++i)
{
	statistics[i] = 0;
}

for(long i = 0; i < 1000; ++i)
{
	int thisRandom = random->LinerCongruentialRandom();
	statistics[thisRandom]++;
	//cout<<"["<<i<<"]:"<<thisRandom<<endl;
}

for(long i = 0; i < 10; ++i)
{
	cout<<"["<<i<<"]:"<<statistics[i]<<endl;
}

计算结果

[0]:94
[1]:114
[2]:105
[3]:90
[4]:98
[5]:101
[6]:91
[7]:105
[8]:91
[9]:111

我们还是可以发现不错的随机性。

C#读取任意charset网页

No Comments

private string GetPageContent(string address)
{
    try
    {
        string result = null;
        HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(address);
        req.Method = "GET";
        using (WebResponse wr = req.GetResponse())
        {
            // 请求网页内容
            Stream stream = wr.GetResponseStream();
            StreamReader sr = new StreamReader(stream, Encoding.Default);
            result = sr.ReadToEnd();

            // 获取网页编码
            int charsetIndex = result.IndexOf("charset");
            string charset = "utf-8";
            if (charsetIndex != -1)
            {
                int right = result.IndexOf(">", charsetIndex);
                charset = result.Substring(
                    charsetIndex + 7, right - charsetIndex - 7).Trim();
                charset = charset.Replace("=", "");
                charset = charset.Replace("\r", "");
                charset = charset.Replace("\n", "");
                charset = charset.Replace("\"", "");
                charset = charset.Replace("'", "");
                charset = charset.Replace("/", "");
                charset = charset.Replace(" ", "").ToLower();
            }

            // 将字符串转换成网页中指定的编码类型
            result = Encoding.GetEncoding(charset).GetString(
                Encoding.Convert(Encoding.Default,
                Encoding.GetEncoding(charset),
                Encoding.Default.GetBytes(result)));

            sr.Close();
            stream.Close();
        }
        return result;
    }
    catch
    {
        return null;
    }
}

对字符串数组生成一个随机序

No Comments

这种情况:
一组照片,或者MP3歌曲,知道它们的路径,保存在一个数组中。现在想随机播放之。要求,每首歌出现的概率相等,且播放完全部之前不会重复,并且保证顺序可以前后无限快进或者快倒。

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace RandomStringArray
{
    class Program
    {
        private static int count = 50;

        static void Main(string[] args)
        {
            string[] originalArray = GetStringArray();
            string[] randomArray = new string[originalArray.Length];

            SortedList<int, string> list = new SortedList<int, string>();
            for (int i = 0; i < originalArray.Length; i++)
            {
                list.Add(originalArray[i].GetHashCode(), originalArray[i]);
            }

            int index = 0;
            foreach (KeyValuePair<int, string> item in list)
            {
                randomArray[index++] = item.Value;
            }

            // Print Result
            Console.WriteLine("Original:");
            for (int i = 0; i < originalArray.Length; i++)
            {
                Console.WriteLine(string.Format("[{0}]{1}", i, originalArray[i]));
            }
            Console.WriteLine("Random:");
            for (int i = 0; i < randomArray.Length; i++)
            {
                Console.WriteLine(string.Format("[{0}]{1}", i, randomArray[i]));
            }
        }

        /// <summary>
        /// Generate a directories list for test
        /// </summary>
        /// <returns>Directories list</returns>
        private static string[] GetStringArray()
        {
            if (!Directory.Exists("Temp"))
            {
                Directory.CreateDirectory("Temp");

                for (int i = 0; i < count; i++)
                {
                    Directory.CreateDirectory("Temp\\" +
                                Guid.NewGuid().ToString());
                }
            }
            return Directory.GetDirectories("Temp");
        }
    }
}