码迷,mamicode.com
首页 > 其他好文 > 详细

有一个demo想开去,程序员在写code的过程中应该想些什么。

时间:2015-08-17 19:59:17      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:

学习c#匿名类的时候,写demo,开始只是两句code,后来一些想法逐步在我的脑海中出现,把这些想法写下来,一方面是见证自己的进步,另一方面也与大家分享如何写一个“优雅”的程序。

  class Program
    {
        public delegate void say(object word);
 
        public delegate int Add(int x, int y);
        public delegate int Sub(int x, int y);
        public delegate int Mul(int x, int y);
        public delegate int Div(int x, int y);
     
        static void Main(string[] args)
        {
            say sayResult = delegate(object word) { Console.WriteLine(word); };
 
            Add add = delegate(int x, int y) { return x + y; };
            Sub sub = delegate(int x, int y) { return x - y; };
            Mul mul = delegate(int x, int y) { return x * y; };
            Div div = delegate(int x, int y) { return x / y; };
 
            sayResult(add(5,6));
            sayResult(sub(5,6));
            sayResult(mul(5,6));
            sayResult(div(5,6));
        }
 
    }

为一段代码,最基本的职能就是要完成功能。在这几句代码中简单的运用了匿名对象实现了加,减,乘,除的运算。但是看上去这段代码有很多相似的语句,在各方面都有很大的提升余地,首先就拿那5个委托开刀,观察4个委托的形式,有相同的签名,相同的返回类型。C#提供了一些做好的委托类型(ActionFunc),事实上并不需要我去定义什么。

 Action<object> sayResult = delegate(object word) { Console.WriteLine(word); };
 
            Func<int, int, int> add = delegate(int x, int y) { return x + y; };
            Func<int, int, int> sub = delegate(int x, int y) { return x - y; };
            Func<int, int, int> mul = delegate(int x, int y) { return x * y; };
            Func<int, int, int> div = delegate(int x, int y) { return x / y; };
 
            sayResult(add(5,6));
            sayResult(sub(5,6));
            sayResult(mul(5,6));
            sayResult(div(5,6));

这样在代码量上面就可以少了5行,但是4个匿名函数在形式和功能上都有一定的相关性,思考集成这4和匿名函数。

这是我开始的想法:

List<Func<int, int, int>> Caculate = new List<Func<int, int, int>>();
            Caculate.AddRange(new Func<int, int, int>[] { add, sub, mul, div });
            sayResult(Caculate[0](5, 6));

很明显代码的长度增加了,多了新的数据成员,在对效率要求不是那么严格的代码中,牺牲代码的长度来换取更好的结构,我认为还是很划算的。但是list中的索引方式不便于使用,假如这个程序集被引用,并不能从单纯的数字上看出什么来。严格的顺序也会增加出错的几率。因此,修改后的代码是这样的:

 Dictionary<string, Func<int, int, int>> Cacular = new Dictionary<string, Func<int, int, int>>();
            Cacular.Add("add", add);
            Cacular.Add("sub", sub);
            Cacular.Add("mul", mul);
            Cacular.Add("div", div);
            sayResult(Cacular["add"](5, 6));

代码再度加长,Dictionary并没提供addrange这种方法。如果需要拓展更多的操作,可以为Dictionary扩展方法addrange来获取更好的可读性。鉴于这是个demo,并未做这方面的工作,现在可以获得更好的集成和可读。说到集成,还有什么能比class更加引人注目呢?Dictionary在这方面太乏力了,首先在代码量上做出了让步,也不能提供智能提示的支持,依旧需要相关的文档支持,才能明晓“键”的含义。是时候将它升格成类了。

public static class Caculate
    {
       public static Func<int, int, int> add = delegate(int x, int y) { return x + y; };
       public static Func<int, int, int> sub = delegate(int x, int y) { return x - y; };
       public static Func<int, int, int> mul = delegate(int x, int y) { return x * y; };
       public static Func<int, int, int> div = delegate(int x, int y) { return x / y; };
}

这里我把运算这4个操作放到caculate类中sayResult独立出去,因为它们并不没有紧密的关系,我又想让这个类 能够支持更多的数据类型,

public static class Caculate<T>
    {
       public static Func<T, T, T>  add = delegate(T x, T y) { return x + y; };
       public static Func<T, T, T>  sub = delegate(T x, T y) { return x - y; };
       public static Func<T, T, T>  mul = delegate(T x, T y) { return x * y; };
       public static Func<T, T, T>  div = delegate(T x, T y) { return x / y; };
}

能这样写多好,可惜泛型不能用于运算符。通过百度获得一个类似的实现。

public static class Cacular<T> where T : struct
    {
 
        public static Func<T, T, T> add = delegate(T x, T y)
        {
            T result = default(T);
            Type type = x.GetType();
            string s = type.ToString();
            switch (type.ToString())
            {
                default: break;
                case "System.Int32":
                    result=  (T)(object)((Int32)(object)x + (Int32)(object)y);
                    break;
                case "System.Single":
                    result = (T)(object)((Single)(object)x + (Single)(object)y);
                    break;
                case "System.Double":
                    result = (T)(object)((double)(object)x + (double)(object)y);
                    break;
            }
            return result;
        };
        public static Func<T, T, T> sub = delegate(T x, T y)
        {
            T result = default(T);
            Type type = x.GetType();
            switch (type.ToString())
            {
                default: break;
                case "System.Int32":
                    result = (T)(object)((Int32)(object)x - (Int32)(object)y);
                    break;
                case "System.Single":
                    result = (T)(object)((Single)(object)x - (Single)(object)y);
                    break;
                case "System.Double":
                    result = (T)(object)((double)(object)x - (double)(object)y);
                    break;
            }
            return result;
        };
        public static Func<T, T, T> mul = delegate(T x, T y)
        {
            T result = default(T);
            Type type = x.GetType();
            switch (type.ToString())
            {
                default: break;
                case "System.Int32":
                    result = (T)(object)((Int32)(object)x * (Int32)(object)y);
                    break;
                case "System.Single":
                    result = (T)(object)((Single)(object)x * (Single)(object)y);
                    break;
                case "System.Double":
                    result = (T)(object)((double)(object)x * (double)(object)y);
                    break;
            }
            return result;
        };
        public static Func<T, T, T> div = delegate(T x, T y)
        {
            T result = default(T);
            Type type = x.GetType();
            switch (type.ToString())
            {
                default: break;
                case "System.Int32":
                    result = (T)(object)((Int32)(object)x / (Int32)(object)y);
                    break;
                case "System.Single":
                    result = (T)(object)((Single)(object)x / (Single)(object)y);
                    break;
                case "System.Double":
                    result = (T)(object)((double)(object)x / (double)(object)y);
                    break;
            }
            return result;
        };   
}

如他所言,这确实是个笨方法,如果有合适的方法,希望联系我。这个类问题老多了,拓展性,可维护都很糟。

现在发现建立个良好的类还是有相当的难度,不仅需要充分考虑当前需要实现的功能,也要考虑将来可能需要拓展的功能,对上兼容,对下拓展,良好的结构,精简的代码。


有一个demo想开去,程序员在写code的过程中应该想些什么。

标签:

原文地址:http://my.oschina.net/u/2403989/blog/493611

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!