代码之家  ›  专栏  ›  技术社区  ›  snicker

扩展“类”:很好地使用扩展方法并提高代码可读性…还是臭味?

  •  0
  • snicker  · 技术社区  · 16 年前

    因此,我最近一直在处理由不同软件供应商为其产品提供的几个API。有时缺少一些东西,有时我只是想让代码更具可读性,我试图避免大量静态方法,因为它们不属于从API“获取我需要的”的范畴。因此,我发现自己编写了很多扩展方法。

    然而,由于有许多方法,并且为了使“我的”方法在代码可读性方面与API对象的方法分开,我提出了以下小花絮:

    public class MyThirdPartyApiExtensionClass {
    
        public static MyThirdPartyApiExtensionClass MTPAEC(this ThirdPartyApiClass value) {
            return new MyThirdPartyApiExtensionClass(value);
        }
    
        private ThirdPartyApiClass value;
    
        public MyThirdPartyApiExtensionClass(ThirdPartyApiClass extendee) {
            value = extendee;
        }
    
        public string SomeMethod() {
            string foo = value.SomeCrappyMethodTheProviderGaveUs();
            //do some stuff that the third party api can't do that we need
            return foo;
        }
    
        public int SomeOtherMethod() {
            int bar = value.WowThisAPISucks(null);
            //more stuff
            return bar;
        }
    
    }
    

    然后我可以做以下事情:

    string awesome = instanceOfApiObject.MTPAEC.SomeMethod();
    

    我把我的东西和他们的完全分开了。

    现在我的问题是。。这似乎是一个好的实践,提高代码可读性。。。或者这是个坏主意?这样做有没有有害的后果?

    免责声明:

    我想同样的分离水平可以简单地这样做:

    public static class MyThirdPartyApiExtensionClass {
    
        public ThirdPartyApiClass MTPAEC(this ThirdPartyApiClass value) {
            return value;
        }
    
        public string SomeMethod(this ThirdPartyApiClass value) {
            string foo = value.SomeCrappyMethodTheProviderGaveUs();
            //do some stuff that the third party api can't do that we need
            return foo;
        }
    
        public int SomeOtherMethod(this ThirdPartyApiClass value) {
            int bar = value.WowThisAPISucks(null);
            //more stuff
            return bar;
        }
    
    }
    
    3 回复  |  直到 7 年前
        1
  •  2
  •   LBushkin    16 年前

    IMHO说,在处理无法修改的API时,扩展方法是一种合理的方法,可以在保持相对解耦的同时扩展API的表达能力。

    扩展方法的最大问题在于,基于名称空间包含(文件顶部的using语句),它们被隐式推断为可用。因此,如果您只是忘记了包含名称空间,那么您最终可能会挠头,想知道为什么没有可用的名称空间。

        2
  •  2
  •   Orion Adrian    16 年前

    为了回答您的直接问题,我认为通过额外的麻烦将您的功能从基本功能中分离出来是一种糟糕的代码味道。从使用角度来看,不要担心代码与它们的代码分离。首先,由于现在有两个地方可以查找相同的功能,因此查找您要查找的内容变得更加困难;其次,语法使您的扩展看起来像是在MTPAEC属性上操作,而不是在核心对象(它们就是这样)上操作。

    我的建议是使用实际的扩展方法,它允许您拥有它,但不需要额外的构造函数。

    public static class ApiExtension
    {
        public static string SomeMethod(this ThirdPartyApiClass value)
        {
            string foo = value.SomeCrappyMethodTheProviderGaveUs();
            //do some stuff that the third party api can't do that we need
            return foo;
        }
    }
    

    var mine = new ThirdPartyApiClass();
    mine.SomeMethod();
    

    剩下的就交给C。

    看你上面的建议,我想你得把这两门课分开。一个用于使用扩展机制提供扩展组,另一个用于提供每组逻辑。

    如果你需要把你的东西和你的一瞥区分开来,那么使用命名约定使你的外观独一无二。尽管悬停并通过intellisense,它会告诉您这是一个扩展方法。

    public static class ApiExtensionder
    {
        public static MTPAEC(this ThirdPartyApiClass value)
        {
            return new MtpaecExtensionWrapper(value);
        }
    }
    
    public class MtpaecExtensionWrapper
    {
        private ThirdPartyApiClass wrapped;
    
        public MtpaecExtensionWrapper(ThirdPartyApiClass wrapped)
        {
            this.wrapped = wrapped;
        }
    
        public string SomeMethod()
        {
            string foo = this.wrapped.SomeCrappyMethodTheProviderGaveUs();
            //do some stuff that the third party api can't do that we need
            return foo;
        }
    }
    
        3
  •  0
  •   JSBÕ±Õ¸Õ£Õ¹    16 年前

    我的观点是,你不必要地增加了一个额外的间接层次。您希望扩展方法在原始对象上可用。。。那为什么不把它们放在那里呢?Intellisense会让您知道这些对象是扩展,这是您真正关心的罕见情况。

    推荐文章