【问题标题】:Is this an efficient way to parse function parameters?这是解析函数参数的有效方法吗?
【发布时间】:2018-10-08 12:56:30
【问题描述】:

所以我是 C# 新手,但我已经喜欢其他高级语言的一件事是能够在(接近)C 中执行按位运算。我有一堆函数,其中一些或所有参数是可选的,而且我喜欢开关,所以我构建了一个将布尔数组转换为无符号短裤的函数,这使我基本上可以将布尔数组复用为开关的单个值:

namespace firstAsp.Helpers{
    public class argMux{                       
        public static ushort ba2ushort (bool[] parms){  
            //initialize position and output                
            ushort result = 0;
            int i = parms.Length-1;
            foreach (bool b in parms){
                if (b)//put a one in byte at position of b
                    //bitwise or with position
                    result |= (ushort)(1<<i);
                i--;
            }
            return result;               
        }
    }
}

这是一个示例用例:

public IActionResult Cheese(string fname,string lname)
    {
        bool[] tf = {fname!=null,lname!=null};

        switch(argMux.ba2ushort(tf)){
         case 3:
            @ViewData["Data"]=$"Hello, {fname} {lname}";
            break;
         case 2:
            @ViewData["Data"]=$"Hello, {fname}";
            break;
         case 1:
            @ViewData["Data"]=$"Hello, Dr. {lname}";
            break;
         case 0:
            @ViewData["Data"]="Hello, Dr. CheeseBurger";
            break;
        }
        return View();
    }

我的问题是,这是一种有效的方法,还是有更好的方法?我的目标是使用简单,这肯定为我提供,但我也希望它是运行时快速的高效代码。任何指针?这是一种愚蠢的做法吗?欢迎任何和所有反馈,如果你相信它,你甚至可以称我为白痴,我不太敏感。谢谢!

【问题讨论】:

  • 这些都不是好的 C#。
  • 我只做了大约 3 天的 C#,所以我不会期待其他任何事情。请向我学习你的方法。

标签: c# bit-manipulation multiplexing


【解决方案1】:

这一切都很糟糕。

编写方法的正确方法是不要使用这些:

public IActionResult Cheese(string firstName, string lastName)
{
    @ViewData["Data"]=$"Hello, {firstName ?? "Dr."} {lastName ?? "Cheeseburger"}";
    return View();
}

我已经喜欢其他高级语言的一件事是能够在(接近)C 中进行按位运算。

如果您正在玩弄比特来解决高级业务问题,那么您可能做错了什么。使用高级业务代码解决高级业务问题。

另外,如果您在 C# 中使用无符号类型,则很有可能您做错了什么。无符号类型用于与非托管代码的互操作性。在 C# 中很少使用 ushort 或 uint 或 ulong 来处理其他任何内容。逻辑上无符号的量,如数组的长度,总是表示为有符号的量。

C# 具有许多旨在确保拥有 COM 库的人可以继续使用他们的库的功能,因此需要指针算术的原始、未经检查的性能的人可以在相当安全的情况下这样做。不要将这些低级编程特性的存在误认为是 C# 通常用作低级编程语言的证据。编写您的代码,使其清楚地作为业务工作流程的实现

您的代码的业务是将名称呈现为字符串,因此它应该清楚地读作将名称呈现为字符串。如果我让你在一张纸上写下一个名字,你要做的第一件事不会是做一个位数组来帮助你,所以它也不应该在这里。

现在,可能在某些情况下,这种事情是明智的,在这些情况下,您应该使用枚举而不是将短作为位字段处理

[Flags]
enum Permissions 
{
  None = 0x00,
  Read = 0x01,
  Write = 0x02,
  ReadWrite = 0x03,
  Delete = 0x04,
  ReadDelete = 0x05,
  WriteDelete = 0x06,
  ReadWriteDelete = 0x07
}
...
static Permissions GetPermission(bool read, bool write, bool delete) {
  var p1 = read ? Permissions.Read : Permissions.None;
  var p2 = write ? Permissions.Write : Permissions.None;
  var p3 = delete ? Permissions.Delete : Permissions.None;
  return p1 | p2 | p3;
}

现在你有一个方便的

switch(p)
{
  case Permissions.None: ...
  case Permissions.Read: ...
  case Permissions.Write: ...
  case Permissions.ReadWrite: ...

但请注意,我们将所有内容都保留在业务域中。我们在做什么? 检查权限。那么代码是什么样的呢? 就像是在检查权限。不要玩弄一堆比特然后打开一个整数。

【讨论】:

  • 这正是我需要的,我不知道有一个运算符可以实现我的确切目标(合并空值)!
  • @ThisGuyCantEven:很好。另外,要改掉fnameba2ushort 等的习惯。如果您输入firstNamePackBooleans 等,您不会死得更早。 使用完整的单词。而且方法应该是描述其行为的动词
  • 注意命名约定建议。是的..我使用无符号的唯一原因是避免对符号位进行额外的数学运算。但现在这些都不重要了。谢谢!
  • @ThisGuyCantEven:您能描述一下您认为符号位可能遇到的问题吗?在大多数情况下,如果您将使用符号位出错,C# 会给您一个警告。此外,我还添加了一些关于在 C# 中执行开关逻辑的正确方法的想法。
  • 好吧,我想我可以从params.length 这样的更高索引开始,而不是params.length-1,以避免符号位出现任何问题。但是我实现它的方式是推到数组中的实际位置,这意味着可能在符号位中放置一个 1,并且肯定会导致除以 2。虽然也许我假设有符号的第一位int 是符号,将 1 放入其中会使值变为负数也是错误的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-09
  • 2012-05-03
  • 2019-08-20
  • 2018-10-27
  • 2011-02-04
  • 2010-12-26
  • 2021-07-26
相关资源
最近更新 更多