最近两天写单元测试,碰到需要验证一个树是否是期望的,但是树这个结构要验证起来还真是有点烦。。。

  我的树大概是这样的:

 class TreeNode<T>
{
private static readonly TreeNode<T>[] Empty = new TreeNode<T>[];
public TreeNode() : this(default(T), Empty) { }
public TreeNode(T value, IReadOnlyList<TreeNode<T>> children)
{
Value = value;
Children = children;
}
public T Value { get; set; }
public IReadOnlyList<TreeNode<T>> Children { get; set; }
}

  为了判等,这个树实现了IEquatable<TreeNode<T>>接口:

         public override bool Equals(object obj)
{
var other = obj as TreeNode<T>;
if (other == null)
{
return false;
}
return Equals(other);
} public bool Equals(TreeNode<T> other)
{
return object.Equals(Value, other.Value) && Children.SequenceEqual(other.Children);
} public override int GetHashCode()
{
return Value.GetHashCode() ^ Children.Aggregate(Children.Count, (seed, x) => seed ^ x.GetHashCode());
}

  看着还不错,不过由于T实际是个复杂类型,每次重写Equals也是个不轻松的事情,而且还要把整个期望的树给构造出来,呵呵,还是烦啊。。。

  但是,如果只需要判定个把简单属性,事情就方便了许多,所以,TreeNode需要一个方法来转换T的类型:

         public TreeNode<TResult> Select<TResult>(Func<T, TResult> selector)
{
return new TreeNode<TResult>(selector(Value), (from c in Children select c.Select(selector)).ToList());
}

  看起来不错,这样就可以有这样的code来玩转tree了:

 TreeNode<int> intTree = ...
TreeNode<string> stringTree = intTree.Select(i => i.ToString());

  等等,我们可以把这代码写的跟linq:

 TreeNode<int> intTree = ...
TreeNode<string> stringTree = from i in intTree
select i.ToString();

  测试代码继续啪啦啪啦的写,唉,测试失败了,什么情况,仔细一看,哦,tree下面节点的顺序错了,而tree的equals方法要求顺序,但是这个测试刚好不要求顺序,于是我有了两个选择:

1. 改写equals方法 (不想折腾集合操作)

2. 让节点排序 (对测试用例而言,构建一个有顺序的树可是很简单的事情)

  所以,我需要个OrderBy:

         public TreeNode<T> OrderBy<TKey>(Func<T, TKey> keySelector)
{
return new TreeNode<T>(Value, (from c in Children
orderby keySelector(c.Value)
select c.OrderBy(keySelector)).ToList());
}

  这下就可以随便折腾这个树了:

 TreeNode<int> intTree = ...
TreeNode<string> stringTree = from i in intTree
let m = i %
order by m
select i.ToString();

一个简单的Linq to TreeNode的更多相关文章

  1. 一个简单的webservice的demo(下)winform异步调用webservice

    绕了一大圈,又开始接触winform的项目来了,虽然很小吧.写一个winform的异步调用webservice的demo,还是简单的. 一个简单的Webservice的demo,简单模拟服务 一个简单 ...

  2. 一个简单的Webservice的demo,简单模拟服务

    前段时间一直在学习WCF,匆匆忙忙的把<WCF全面解析>和<WCF服务编程>看了一遍,好多东西都不是很懂,又听了一下WCF分布式开发的网络教程,算是马马虎虎的明白点了.回顾了一 ...

  3. 推荐一个简单、轻量、功能非常强大的C#/ASP.NET定时任务执行管理器组件–FluentScheduler定时器

    在C#WINFORM或者是ASP.NET的WEB应用程序中,根据各种定时任务的需求,比如:每天的数据统计,每小时刷新系统缓存等等,这个时候我们得应用到定时器这个东东. .NET Framework有自 ...

  4. WCF服务二:创建一个简单的WCF服务程序

    在本例中,我们将实现一个简单的计算服务,提供基本的加.减.乘.除运算,通过客户端和服务端运行在同一台机器上的不同进程实现. 一.新建WCF服务 1.新建一个空白解决方案,解决方案名称为"WC ...

  5. 用 C# 实现一个简单的 Rest Service 供外部调用

    用 C#  实现一个简单的 Restful Service 供外部调用,大体总结为4点: The service contract (the methods it offers). How do yo ...

  6. 一个简单的web服务器

    写在前面 新的一年了,新的开始,打算重新看一遍asp.net本质论这本书,再重新认识一下,查漏补缺,认认真真的过一遍. 一个简单的web服务器 首先需要引入命名空间: System.Net,关于网络编 ...

  7. C#一个简单下载程序实例(可用于更新)

    运行时的界面 using System; using System.Collections.Generic; using System.ComponentModel; using System.Dat ...

  8. 一个简单的webservice调用

    我们先创建一个简单空web应用程序 然后添加新建项目 //我们创建一个peson对象,产生数据标识返回 using System; using System.Collections.Generic; ...

  9. oracle常见为题汇总,以及一个简单数据连接操作工厂

    本人软件环境:win8.1 64位操作系统,vs2013,安装好了与oracle数据库对应的客户端         连接oracle数据库.以及操作数据库 1.使用IIS建立网站,浏览网页时候,提示“ ...

随机推荐

  1. ftp文件上传下载实用命令

    连接 >ftp yourhost >user yourusername >password your password 顺利的话连接成功 >dir ;获取remote目录列表 ...

  2. android TextView多行文本(超过3行)使用ellipsize="end"属性无效问题的解决方法

    <TextView android:id="@+id/desc" android:layout_width="match_parent" android: ...

  3. 两种方法设置disabled属性

    //两种方法设置disabled属性 $('#fileup').attr("disabled",true); $('#fileup').attr("disabled&qu ...

  4. Android Studio添加aar

    1.把aar复制到项目中的 libs 里面 2.在module 里面的build.gradle 的根目录添加 repositories{ flatDir { dirs 'libs' } } 3.在mo ...

  5. CocoaPods升级安装三方库报错

    CocoaPods升级后(最新版本1.0.1),安装第三方库的时候会报如下错误: The dependency `AFNetworking (~> 3.1.0)` is not used in ...

  6. javascript 常见方法记录

    1,trim():去除字符串左右两端的空格,在vbscript里面可以轻松地使用 trim.ltrim 或 rtrim,但在js中却没有这3个内置方法,需要手工编写. <script langu ...

  7. linux版基金看板

    程序员的吊丝们,还在害怕上班时偷偷看基金被老板发现吗?今天你们的福利来了,专属程序员吊丝一族的礼物,linux版基金看板. 优点: 1.自定义设置关注基金 2.linux系统,让别人可以以为你一直都在 ...

  8. ajax参数设置略解

    通过ajax可以直接由页面访问到服务器.做到不刷新页面,就能刷新数据,为开发带来很大的便利. 1.ajax方式的参数及其功能: $.ajax({ type : "POST", // ...

  9. Java暗箱操作之for-each

    对于我们常用的ArrayList等容器类,经常需要一个一个遍历里面的元素,从而对各个元素执行对应的操作. 像我代码写多了,通常的做法是用传统的,类似于数组遍历的方法,即在for循环中设置一个int变量 ...

  10. Linux命令学习总结:shutdown

    命令简介: 该命令可以安全关闭或者重新启动系统.你没有看错,shutdown命令不仅可以关闭系统.也可以重启Linux系统.   命令语法: /sbin/shutdown [-t sec] [-ark ...