扩展方法 之 基本数据篇

 C# 中有两种基本数据类型:值类型和引用类型。 值类型包括:简单类型、结构类型、枚举类型;引用类型包括:Object 类型、类类型、接口、代表元、字符串类型、数组。

  说白了这篇就是扩展 int, string, double, DateTime...等基本类型。这么多数据类型,如果int来个扩展,double也来个扩展,肯定会是一个造金字塔工程。幸好有泛型帮我们,但是有时泛型也不是万能的,这个以后有机会再说。

  为什么我们需要扩展方法?一句话:提高写代码的速度,语义也清晰。按道理说,基于基本数据的扩展方法应该经常被用到才有意义,否则只会“污染”被扩展的元素。而怎么才算常用,这可没什么标准,也不是我一个人说了算。所以,以下的扩展方法大家就根据自己的经验判断是否常用吧,至少我的项目是用了不少。

1. In 判断一个元素是否在一个集合里面

(这是我目前为止见到最好的扩展方法之一)

1.1 ScottGu 最初的版本:

step2  

1.2 后经 鹤冲天 的润色:c#扩展方法奇思妙用高级篇一:改进 Scottgu 的 "In" 扩展

      //ScottGu In扩展 改进
        public static bool In(this T t, params T[] c)
        {
            return c.Any(i => i.Equals(t));
        }

1.3 最后我也来凑个热闹:

   public static bool In(this T t, params T[] c)
        {
            return c.Contains(t);
            //return c.Any(i => i.Equals(t));
        }

示例:

bool exist1=  2.In(1, 2, 3);
string[] helloworld = { "Hello", "World", "!" };
bool exist2 = "Hello".In(helloworld );

2. InRange 判断一个元素是否在某个范围

public static bool InRange(this IComparable t, T minT, T maxT)
        {
            return t.CompareTo(minT) >= 0 && t.CompareTo(maxT) <= 0;
        }
        public static bool InRange(this IComparable t, object minT, object maxT)
        {
            return t.CompareTo(minT) >= 0 && t.CompareTo(maxT) <= 0;
        }

示例:

//判断3是否在2~3的范围
bool result1 = 3.InRange(2, 3);
 //判断3.14是否在3.13~3.15的范围
bool result2 = 3.14.InRange(3.13, 3.15);
//判断今天是否在2000年1月1日~2010年1月1日的范围
bool result3 = DateTime.Now.InRange(new DateTime(2000, 1, 1), new DateTime(2010, 1, 1));
//判断牛B是否在牛A和牛C之间
bool result4 = "牛B".InRange("牛A", "牛C");

上面最后一个示例来源于这句网语:做一个徘徊于牛A和牛C之间的人

3. ForEach 遍历集合

public static void ForEach(this IEnumerable source, Action action)
{
           foreach (T element in source)
           action(element);
}         
public static void ForEach(this IEnumerable source, Actionint> action)
{
            int i = 0;
            foreach (T element in source)
            action(element, i++);
 }

注:这两个并非原创,但实在太通用,已经找不到出处。

示例1:Linq to SQL 批量更新

//Linq to SQL 
IQueryable query = ...;
query.ForEach(c => c.Name = "Bruce");
db.SubmitChanges();

示例2:设置行号

List list = ...;
list.ForEach((c,i) => c.Line = (i+1)); 

4. Clone 克隆一个对象

public static T Clone(this T t)
 {
       return (T)CloneObject(t);
}
        private static object CloneObject(object obj)
 {
            using (MemoryStream memStream = new MemoryStream())
        {
                BinaryFormatter binaryFormatter = new BinaryFormatter(null,   
                new StreamingContext(StreamingContextStates.Clone));
                binaryFormatter.Serialize(memStream, obj);
                memStream.Seek(0, SeekOrigin.Begin);
                return binaryFormatter.Deserialize(memStream);
        }
 }

示例1:克隆单个实体

Entity entity = new Entity { Name = "Bruce", Line = 1 };
            Entity cloneEntity = entity.Clone();
            bool same = entity.Equals(cloneEntity);
            // 被克隆的类必须标记为可序列化
             [Serializable]
            class Entity
           {
                  public string Name { get; set; }
                  public int Line { get; set; }
            }

最后entity.Equals(cloneEntity);的结果是false,表明已经成功克隆了一个新对象。

示例2:克隆集合

List list = new List();
            list.Add(new Entity { Name = "Bruce", Line = 1 });
            list.Add(new Entity { Name = "Jack", Line = 2 });
            list.Add(new Entity { Name = "Rose", Line = 3 });
            list.Add(new Entity { Name = "Tony", Line = 4 });
            List cloneList = list.Clone();

总结:

扩展方法为我们封装了常用的逻辑,与以往静态方法不同的是,从使用者的角度来看已经不用关心这个方法是来自于那个类,主要记着命名空间就可以。所以,一般做法是,所有扩展方法属于同一命名空间,并按被扩展的类型分类,如下图:

image

最后要说的是,其实string类型的扩展方法应该是使用频率最高的,但基于string的扩展方法网上随便一抓一大把,这里就不重复列举了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值