C#重复代码行vs从内存使用情况角度使用属性

问题描述:

我想知道是否有更好的方法来实现可维护性和内存影响的观点下面的代码。看下面的代码会更好地使用属性?我看到很多重复的代码,我想知道最好的方法是什么。C#重复代码行vs从内存使用情况角度使用属性

public class Win32OperatingSystem 
{ 
    internal ulong BytesToMegaBytes(ulong bytes) 
    { 
     return bytes/(ulong)1024; 
    } 

    public ulong FreePhysicalMemory() 
    { 
     ManagementObjectSearcher moSearcher = new ManagementObjectSearcher 
      ("SELECT FreePhysicalMemory FROM Win32_OperatingSystem"); 
     using (var enu = moSearcher.Get().GetEnumerator()) 
     { 
      if (!enu.MoveNext()) return 0; 
      return BytesToMegaBytes((ulong)enu.Current["FreePhysicalMemory"]); 
     } 
    } 

    public ulong TotalVirtualMemorySize() 
    { 
     ManagementObjectSearcher moSearcher = new ManagementObjectSearcher 
      ("SELECT TotalVirtualMemorySize FROM Win32_OperatingSystem"); 
     using (var enu = moSearcher.Get().GetEnumerator()) 
     { 
      if (!enu.MoveNext()) return 0; 
      return BytesToMegaBytes((ulong)enu.Current["TotalVirtualMemorySize"]); 
     } 
    } 

    public ulong FreeVirtualMemory() 
    { 
     ManagementObjectSearcher moSearcher = new ManagementObjectSearcher 
      ("SELECT FreeVirtualMemory FROM Win32_OperatingSystem"); 
     using (var enu = moSearcher.Get().GetEnumerator()) 
     { 
      if (!enu.MoveNext()) return 0; 
      return BytesToMegaBytes((ulong)enu.Current["FreeVirtualMemory"]); 
     } 
    } 
} 

而不是重复的方法可能会更好做这样的事情......

MyMethod(string propertyName) 
{ 
     ManagementObjectSearcher moSearcher = new ManagementObjectSearcher 
      ("SELECT " + propertyName + " FROM Win32_OperatingSystem"); 
     using (var enu = moSearcher.Get().GetEnumerator()) 
     { 
      if (!enu.MoveNext()) return 0; 
      return BytesToMegaBytes((ulong)enu.Current[propertyName]); 
     } 
    } 
+2

将重复的代码块折叠成通用函数当然看起来是一种很好的方法。你有什么理由不这样做? – David

+0

如果你不信任传入的字符串,你可以使用枚举,但对于你的问题,它的方式很好 – Jonesopolis

+0

你有很多重复代码,所以将它折叠成通用目的,然后使用accessor方法将有助于维护持续。代码大小可能会更小,虽然微不足道...... – LB2

使用DRY原则会使你的第二个选择最好的一个(忽略缺少的SQL参数这个例子)。它的代码更少,易于维护。但是,如果修复代码的开发人员不知道调用此函数的所有位置,则可能会导致错误。

我会倾向于使用单个私有方法,然后从公共方法调用它。

public class Win32OperatingSystem 
{ 
    internal ulong BytesToMegaBytes(ulong bytes) 
    { 
     return bytes/(ulong)1024; 
    } 

    public ulong FreePhysicalMemory() 
    { 
     return GetProperty("FreePhysicalMemory"); 
    } 

    public ulong TotalVirtualMemorySize() 
    { 
     return GetProperty("TotalVirtualMemorySize"); 
    } 

    public ulong FreeVirtualMemory() 
    { 
     return GetProperty("FreeVirtualMemory"); 
    } 

    private ulong GetProperty(string propertyName) 
    { 
     ManagementObjectSearcher moSearcher = new ManagementObjectSearcher 
      ("SELECT " + propertyName + " FROM Win32_OperatingSystem"); 
     using (var enu = moSearcher.Get().GetEnumerator()) 
     { 
      if (!enu.MoveNext()) return 0; 
      return BytesToMegaBytes((ulong)enu.Current[propertyName]); 
     } 
    } 
} 

当然,这就是DRY原理的意义所在。

但是不要用那个替换其他3种方法。让你的新方法变得私人化(并且当你处于这个状态时,给它一个更好的名字),并让其他3个人称它。

public ulong FreePhysicalMemory() 
{ 
    return FindMemoryObject("FreePhysicalMemory"); 
} 

这不仅是维护好,但也为可读性。

至于性能或记忆 - 不用担心。是的,还有一个额外的抽象层次,一种方法必须被调用(并且可能不会被内联),但这是微型优化。追求可读性+可维护性。

对内存的影响可以忽略不计,但通过在很多方法中重复实现来违反DRY principle不利于可维护性:是的,最好是按照您的建议进行操作。

+0

正如其他人指出的那样,确保新方法是私有的,并且您称之为内容的每个属性方法仍然是公共的。我认为这是不言而喻的,但它可能值得注意。 – J0e3gan