使用C#中的扩展方法构建自己的工具箱

扩展方法是C#最酷的功能之一。 它允许我们在对象上使用我们的自定义方法,而无需扩展或更改基础类。

扩展方法不过是静态方法。 您可以像调用其他任何静态方法一样直接调用它们。

public sealed class User {
	public int Id { set ; get ;}
	public string Name { set ; get ;}
	public int Age { set ; get ;}
	public StatusCode Status { set ; get ;}
}

让我们为该类添加一个扩展方法,该方法检查该用户是否处于活动状态。

public static class UserExtensions {
	public static bool IsActive ( this User user) {
		return user.Status == User.StatusCode.Active;
	}
}
...
userObj.IsActive();
...

您可能正在考虑有什么大不了的事,我们可以在User类本身中添加此方法。 但是,我们可能并不总是拥有对类的控制权。 它可能来自第三方库,我们可能无法扩展该类以添加此方法(因为sealed )。 那就是扩展方法大放异彩的地方! 这只是一个静态方法,它只能访问对象的公共接口。 但是,它看起来像对象具有方法,并且允许我们以声明的方式编写代码。

扩展方法只是静态方法。 this关键字与静态方法唯一不同。 您也可以像常规静态方法一样调用它,并且将以相同的方式工作: UserExtensions.IsActive(userObj)

那工具箱呢?

我们著名的Linq库只不过是扩展方法的集合。 可能我们大多数人都做了以下很多工作。

var list = userList
. Where( i => i .Status == User.StatusCode.Active) ;

我们可以通过添加自己的扩展方法来创建工具箱,因此可以使用新的扩展方法来改进代码。

var list = userList
. Where( i => i .IsActive() );

我们可以通过添加另一种扩展方法来更进一步。

public static IEnumerable<User> OnlyActive( this IEnumerable<User> list) {
  return list.Where( i => i.IsActive());
}

现在我们的代码简化为:

userList
.OnlyActive();

我们也可以添加其他方法。

public static IEnumerable<User> OlderThan( this IEnumerable<User> list , int age ) {
  return list . Where( i => i .Age > age ) ;
}

public static IEnumerable<User> YoungerThan( this IEnumerable<User> list , int age ) {
  return list . Where( i => i .Age < age ) ;
}

public static User GetById( this IEnumerable<User> list , int Id) {
  return list . SingleOrDefault( i => i .Id == Id) ;
}

因此我们可以编写如下。 代码不言自明...

userList
.OnlyActive()
.YoungerThan(20);

我们还可以添加更多通用方法。

public static class OtherExtensions {
	public static bool IsNull ( this object obj ) {
		return obj == null ;
	}
	
	public static bool IsNotNull ( this object obj ) {
		return !obj.IsNull();
	}
	
	public static void IfNotNull<T>( this T obj, Action<T> action){
		if (obj.IsNotNull()){
			action(obj);
		}
	}
}

也可以像上一个方法IfNotNull一样使用泛型。 它期望一个类型为T的对象,如果它不是null ,它将调用传入的委托函数。

var exists = userList
. GetById(30)
. IsNotNull() ;


userList
. GetById(3)
. IfNotNull( user => Console.WriteLine( user .Name + " found!" ) );

结论

扩展方法是抽象逻辑的好方法。 它的声明性使代码库更简洁易读。

https://dotnetfiddle.net/JGmKGi

From: https://hackernoon.com/building-your-own-toolbox-with-extension-methods-f18q36op

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VS风格的ToolBox和QQ的界面很相似,都是有多个栏目,并且这些栏目可以展开和折叠,当鼠标在某个子栏目上时,可以高亮显示,另外在VS风格的ToolBox,点击选项目的时候,要用特殊的颜色标识出来。 1. 创建控件的边框,我在前边的文章也讲过(),直接将代码复制过来,稍做修改即可。 2. 添加滚动条,因为我们的控件只需要垂直的滚动,所以我只只加入一个垂直的滚动条。 3. ToolBox包含多个Category,我们不但要创建Category类,还要创建这个类的集合。 4. 每一个Category包含多个Item,我们不但要创建ToolBoxItem类,还要创建这个类的集合。 5. 重载OnPaint方法,绘制控件的内容,在绘制的时候要注意滚动条的当前值,由于采用了双缓冲机制,所以每次总是将所有的内容重绘一次,不考虑ClipRect。 6. 写一个方法,根据鼠标的坐标计算出鼠标指向的Item或者Category,这个方法是这个控件的核心。 7. 重载OnMouseMove方法,当鼠标指向某个Item的时候,高亮显示出来。 8. 重载 OnMouseDown方法,当鼠标在某个Item上按下的时候,用指定的颜色标识出来,如果鼠标按下的地方是一个Category,根据当前的情况展开或者时折叠这个category。 9. 计算控件当前状态的内容的总的高度,用于设置滚动条的可见与不可见。 10. 暴露一个属性,用于为用户提供当前选的Item。 11. 声明一个ItemChanged事件,便于用户在选择另一个Item时添加处理的代码。 实现了上述的内容,这个控件也就基本完成了。由于代码并不复杂,我就不将代码列出来讲解了,我将提供代码的下载,大家在看代码的时候,如有不明白的地方,可以参考我前面的控件教程。因为只花了几个小时写的这个控件,难免还有一些问题,请大家指出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值