代码改变世界

应用.Net 扩展方法实现更短的流程控制

2011-11-03 15:10  chris-shao  阅读(1638)  评论(2编辑  收藏  举报

最近看Ruby方面的书,里面有些更简单的代码给我们一些思路,是应该使代码更加的简短,同时强化每段代码的含义将会让代码更加易读,其中关于简化流程控制的代码非常吸引人,比如:简单的 5.each{puts:x},就实现了5次循环,并对循环变量做操作。

 

另外,例如["a","b","c"].each_with_index{|x,i|printf "%d: %s\n",i,x} 也实现了对数组的访问和操作。

 

相比早期的到处写for循环相比,这样的代码更具有吸引力吧。

 

在.Net中,我们也可以通过扩展方法来实现相同的简化,我做了如下代码以演示:

这部分代码目的为了给一个数组对象扩展Each方法,另外,实现了对一个int类型的对象增加For方法,实现如上Ruby中的流程控制。

另外为数组增加了If循环,即当条件满足时再调用方法。

public static class SystemExt
    {
        public delegate void EachMethod<TSource>(TSource obj);
        public static void Each<TSource>(this IEnumerable<TSource> source, EachMethod<TSource> method)
        {
            foreach (TSource obj in source)
            {
                method(obj);
            }
        }
        public static void If<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> selector, EachMethod<TSource> method)
        {
            foreach (TSource obj in source)
            {
                if (selector(obj))
                    method(obj);
            }
        }
        public static void For(this int max, Func<int,bool> method)
        {
            for (int i = 0; i < max; i++)
            {
                if (!method(i))
                {
                    break;
                }
            }
        }
    }

将上面的类加入解决方案后,就可以很容易的调用了。

 

string[] i = new string[] { "a""b" };
            i.Each(x => Response.Write(x));
            i.If(x => x == "a", x => Response.Write(x));
            5.For(c => { Response.Write(c); return c!=3; });

 

通过自定义的流程控制,可以看到,代码量的减少,逻辑代码更清晰,应该值得推广。

 

另外,可通过扩展方法来实现单位。

如下代码实现单位年月日,以及部分计算:

如下代码可以实现:

12.Month() + 2000.Year() + 3.Day()
这样的运算。

public struct Year
    {
        private int _year;
        public Year(int year)
        {
            _year = year;
        }
        public int YearNumber
        {
            get { return _year; }
        }
        public static YearMonth operator +(Year year,Month month)
        {
            return new YearMonth(year, month);
        }
    }
    public struct Month
    {
        private int _month;
        public Month(int month)
        {
            _month = month;
        }
        public int MonthNumber
        {
            get { return _month; }
        }
        public static YearMonth operator +( Month month,Year year)
        {
            return new YearMonth(year, month);
        }
    }
    public struct Day
    {
        private int _day;
        public Day(int day)
        {
            _day = day;
        }
        public int DayNumber
        {
            get { return _day; }
        }

    }
    public struct YearMonth
    {
        private Month _month;
        private Year _year;
        public YearMonth(Year year,Month month)
        {
            _month=month;
            _year=year;
        }
        public static DateTime operator +( YearMonth month,Day day)
        {
            return new DateTime(month._year.YearNumber, month._month.MonthNumber, day.DayNumber);
        }
 
    }
    
    public static class SystemExt
    {
        public static Year Year(this int max)
        {
            return new Year(max);
        }
        public static Month Month(this int max)
        {
            return new Month(max);
        }
        public static Day Day(this int max)
        {
            return new Day(max);
        }
        
        
    }