【问题标题】:C# - Downside to Setting Initial Value in DeclarationC# - 在声明中设置初始值的缺点
【发布时间】:2011-03-01 05:02:33
【问题描述】:

这样的课程有什么缺点吗:

class Example1
{
  protected string UserId = (string)Session["user"];
}
//versus

class Example2
{
  protected string UserId;
  public Example2()
  {
      UserId = (string)Session["user"];
  }
}

如果我总是想设置这个值,Example1 有什么缺点吗?

更新:
Session["user"] 在 Global.asax Session_Start 中设置。所以如果这失败了。无论如何都不应该工作。

【问题讨论】:

  • 我最喜欢使用合并运算符 UserId = (string) Session["user"] ?? "0";
  • 这个应用程序使用了整个地方的合并操作,因为有很多变量被传递。我们在每个 WebForm 继承自的“BasePage”中执行此操作
  • 我一直在纠结这个问题。 +1

标签: c# .net oop instantiation


【解决方案1】:

主要缺点是您只能使用单个语句设置值。例如,如果您想检查 Session 密钥是否存在,而如果它不存在,您想为其分配一个值,那么您无法通过设置初始值来实现。

【讨论】:

    【解决方案2】:

    你最大的问题是如果这个protected string UserId = (string)Session["user"]; 失败了。你没有办法优雅地降级。通过将其放入构造函数等中。您可以检查 Session 并决定要做什么。

    作为一般规则,我只尝试输入我知道会成功的值,例如UserId = -1; 等,然后在需要时在代码块中修改它们。你永远不知道什么时候会出错,你需要从中恢复。

    【讨论】:

      【解决方案3】:

      如果您签入调试器,则声明(示例 1)中的值设置发生在调用构造函数之前,因此您需要确保它不依赖于构造函数设置的任何内容。

      【讨论】:

        【解决方案4】:

        我强烈建议使用“安全”演员表。

        UserId = Session["user"] as string;
        

        这样,如果会话项不存在,或者不是字符串,则不会失败。您只需获得一个 null,您可以在使用 UserId 之前对其进行测试。

        【讨论】:

        • 在这种情况下,安全投射的使用太多了。如果它不是一个字符串,我想你可能会想要一个错误。您在第一个地方编写代码,并且您期望一个字符串,因此如果它不是字符串,则应将其作为需要修复的问题提出。我见过太多的系统表现出奇怪的行为,因为错误的类型被存储在某个地方,并且安全转换隐藏了真正的错误并使它看起来像一个未初始化的变量错误。只是我的两分钱。
        • 他的评论(在您的回答之后添加)指出Session["user"] 必须是一个字符串,因此最好将问题扼杀在萌芽状态跨度>
        • 只要您知道可能发生异常,就应该始终选择引发异常。也许在这种情况下让异常发生是正确的,但也可能不是。安全铸造给你一个选择。
        • 我几乎只使用不安全的演员表。这样,在没有任何额外检查的情况下,我得到了一个快速失败的行为,代码在它应该中断的地方中断,而不是三个分类和两个方法。
        • @SWeko,这可能是您想要的行为,但可能不是用户想要的行为。我宁愿优雅地处理错误,并且不中断地恢复。
        【解决方案5】:

        AFAIK,内联值初始化程序和构造函数初始化之间没有真正的区别,除了语句的执行顺序,以及您在内联代码中非常受限于单行语句这一事实。

        执行顺序是值初始化程序在任何构造函数逻辑之前执行,以非特定顺序执行,因此如果任何初始化语句碰巧有副作用,您可能会遇到一些令人讨厌的意外。但是,保证该代码会运行,因此以后不会添加额外的构造函数,而忘记初始化某些字段。

        我更喜欢使用(链式)构造函数来进行内联初始化,因为我发现这样的代码更具可读性,而且我还可以进行任何可能需要的额外检查。

        【讨论】:

          【解决方案6】:

          我使用的指导方针:使用字段初始化器作为编译时已知的基本/值。如果您正在执行诸如查找全局集合或一些重要逻辑之类的操作,请将其移至 ctor(如其他人所指出的那样用于错误处理/恢复)。

          假设你确定没有错误,

          • 优点:字段初始值设定项易于阅读。
          • 缺点:如果您有一堆字段初始化器和多个 ctor,则初始化器的 IL 将插入到 每个 ctor 的顶部,从而导致一些 IL 膨胀。所以在这种情况下,调用类似 Initialize 的方法会更好。

          除此之外,我认为字段初始化器没有任何缺点。

          【讨论】:

            【解决方案7】:

            很难知道如何开始说这不是一个好主意,原因有很多。 First Session 必须是全局变量,否则您的代码甚至无法编译。我猜你的上下文中的 Session 是 System.Web.HttpContext.Current.Session,所以,你的代码甚至不会编译。假设你有 Session 作为全局变量,那么你必须正确初始化它并赋值 Session["user"],那么你打算怎么做呢?然后你在你的类和会话之间创建这种依赖关系,那么你如何进行单元测试呢?加上所有其他答案的所有其他原因。

            【讨论】:

              【解决方案8】:

              有一天,您可能需要另一个具有不同 UserId 值的构造函数。

              【讨论】:

                【解决方案9】:

                AFAIK 构造函数总是在所有字段被初始化后被调用。所以在示例 2 中,您首先将字段初始化为 Null,然后再初始化为 (string)Session["user"]

                【讨论】:

                  猜你喜欢
                  • 2021-09-02
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-02-23
                  • 1970-01-01
                  • 2019-12-01
                  • 1970-01-01
                  • 2010-11-20
                  • 1970-01-01
                  相关资源
                  最近更新 更多