C# 确保对象不为null

C# 确保对象不为null,c#,coding-style,exception-safety,C#,Coding Style,Exception Safety,如何确保类的某个实例永远不会为null?有人告诉我使用Debug.Assert(),但这样做,我只会确保代码在调试模式下工作,而我想确保发布版中的条件永远不为null 例如,过去我编写的代码如下: public string MyString { get { if(instance1.property1.Equals("bla")) { return bla; } } } 但如果instance1为null,则会引发异常。我希望今后避免犯这样的错误,避

如何确保类的某个实例永远不会为null?有人告诉我使用Debug.Assert(),但这样做,我只会确保代码在调试模式下工作,而我想确保发布版中的条件永远不为null

例如,过去我编写的代码如下:

public string MyString
{
get
{
    if(instance1.property1.Equals("bla"))
    {
        return bla; 
    }
}
}
但如果instance1为null,则会引发异常。我希望今后避免犯这样的错误,避免产生这样的例外情况

谢谢


请参见下面说明问题的具体示例:

我有一种基于服务器响应对用户进行身份验证的方法。方法如下:

        /// <summary>
    /// attempts authentication for current user
    /// </summary>
    /// <returns></returns>
    public AuthResult CheckUser()
    {
        WebRequest request = WebRequest.Create(GetServerURI);
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";

        string postdata = "data=" + HttpUtility.UrlEncode(SerializeAuth());
        byte[] arr = Utils.AppDefaultEncoding.GetBytes(postdata);
        request.ContentLength = arr.Length;
        request.Timeout = Convert.ToInt32(TimeUtils.GetMiliseconds(10, TimeUtils.TimeSelect.Seconds));

        Stream strToWrite = request.GetRequestStream();
        strToWrite.Write(arr, 0, arr.Length);

        WebResponse response = request.GetResponse();
        using (Stream dataFromResponse = response.GetResponseStream())
        {
            using (StreamReader reader = new StreamReader(dataFromResponse))
            {
                string readObj = reader.ReadToEnd();
                return DeserializeAuth(readObj);
            }
        }
    }
除其他外,我还拥有这一财产

        public ResultType AuthResult
    {
        get
        {
            if (_authenticationResult.auth == "1")
                return ResultType.Success;
            if (_authenticationResult.auth == "0")
                return ResultType.FailAccountExpired;
            if (_authenticationResult.auth == "-1")
                return ResultType.FailWrongUsernameOrPassword;
            if (_authenticationResult.auth == "-2")
                return ResultType.Banned;


            return ResultType.NoAuthDone;
        }
    }

public enum ResultType { Success, FailWrongUsernameOrPassword, FailAccountExpired, NoAuthDone, Banned }
发生的情况是_authenticationResult有一次为null,并且属性AuthResult在尝试“null.auth”时抛出了一个nullref。我如何确保(可能在CheckUser()方法中)它永远不会返回null

当我调试应用程序时,它从未发生过。但在生产环境中,当服务器超时时,该方法有时返回null

谢谢,

您可以使用:

if ( instance1 != null && instance1.property1.Equals("bla")){
   // Your code 
 } 
您可以使用:

if ( instance1 != null && instance1.property1.Equals("bla")){
   // Your code 
 } 

我认为您需要了解如何实例化
instance1
,以及随后如何实例化
property1
,并且只以不能为null的方式实例化它们。这通常通过在构造时检查参数来实现,例如:

public instance1(string property1)
{
    if (property1 == null) throw new ArgumentNullException("property1");

    this.property1 = property1;
}
如果您创建类型的方式使它们不能以无效状态存在,则可以确保依赖代码不会落入
null

否则,我们需要看到一个更完整的例子,你正在做什么,给你更具体的建议

另一个要考虑的是,你的阶级可以存在什么样的状态,它是一种需要的操作状态,而不是一种可选的操作状态。也就是说,您的类需要哪些成员才能运行,您应该努力设计类,使其始终具有所需状态,例如:

public class Person
{
  public Person(string forename, string surname)
  {
    if (forename == null) throw new ArgumentNullException("forename");
    if (surname == null) throw new ArgumentNullException("surname");

    Forename = forename;
    Surname = surname;
  }

  public string Forename { get; private set; }
  public string Surname { get; private set; }
}
在我的示例类型中,我要求我的
值具有非空值。这是通过我的构造函数强制执行的。。。my
Person
类型永远不能用空值进行实例化(尽管,空值可能同样糟糕,因此检查
IsNullOrWhiteSpace
并抛出适当的
ArgumentException
是一条路线,但让我们保持简单)

如果我要引入一个可选字段,我会允许它改变我的
Person
实例的状态,例如,给它一个setter:

public class Person
{
  public Person(string forename, string surname)
  {
    if (forename == null) throw new ArgumentNullException("forename");
    if (surname == null) throw new ArgumentNullException("surname");

    Forename = forename;
    Surname = surname;
  }

  public string Forename { get; private set; }
  public string Surname { get; private set; }

  public string Initial { get; set; }
}
My
Person
类型仍然强制执行操作所需的字段,但引入了可选字段。然后,在执行使用这些成员的操作时,我需要考虑这一点:

public override ToString()
{
  return Forename + (Initial == null ? String.Empty : " " + Initial) + " " + Surname;
}

(虽然这不是
ToString
的最佳示例)。

我认为您需要了解如何实例化
实例1
,以及随后的
属性1
,并且只以不能为空的方式实例化它们。这通常通过在构造时检查参数来实现,例如:

public instance1(string property1)
{
    if (property1 == null) throw new ArgumentNullException("property1");

    this.property1 = property1;
}
如果您创建类型的方式使它们不能以无效状态存在,则可以确保依赖代码不会落入
null

否则,我们需要看到一个更完整的例子,你正在做什么,给你更具体的建议

另一个要考虑的是,你的阶级可以存在什么样的状态,它是一种需要的操作状态,而不是一种可选的操作状态。也就是说,您的类需要哪些成员才能运行,您应该努力设计类,使其始终具有所需状态,例如:

public class Person
{
  public Person(string forename, string surname)
  {
    if (forename == null) throw new ArgumentNullException("forename");
    if (surname == null) throw new ArgumentNullException("surname");

    Forename = forename;
    Surname = surname;
  }

  public string Forename { get; private set; }
  public string Surname { get; private set; }
}
在我的示例类型中,我要求我的
值具有非空值。这是通过我的构造函数强制执行的。。。my
Person
类型永远不能用空值进行实例化(尽管,空值可能同样糟糕,因此检查
IsNullOrWhiteSpace
并抛出适当的
ArgumentException
是一条路线,但让我们保持简单)

如果我要引入一个可选字段,我会允许它改变我的
Person
实例的状态,例如,给它一个setter:

public class Person
{
  public Person(string forename, string surname)
  {
    if (forename == null) throw new ArgumentNullException("forename");
    if (surname == null) throw new ArgumentNullException("surname");

    Forename = forename;
    Surname = surname;
  }

  public string Forename { get; private set; }
  public string Surname { get; private set; }

  public string Initial { get; set; }
}
My
Person
类型仍然强制执行操作所需的字段,但引入了可选字段。然后,在执行使用这些成员的操作时,我需要考虑这一点:

public override ToString()
{
  return Forename + (Initial == null ? String.Empty : " " + Initial) + " " + Surname;
}

(虽然这不是
ToString
的最好例子。)

因为
instance1.property1
永远不应该为null,请查看是否有方法正确初始化它,如果有人试图将其设置为null,则抛出
ArgumentNullException

例如:

public string Property1
{
    set 
    {
      if(value == null)
      {
        throw new ArgumentNullException();
      } 
      instance1.property1 = value;
    }
}

由于
instance1.property1
不应为null,请查看是否有方法正确初始化它,如果有人试图将其设置为null,则抛出
ArgumentNullException

例如:

public string Property1
{
    set 
    {
      if(value == null)
      {
        throw new ArgumentNullException();
      } 
      instance1.property1 = value;
    }
}

就个人而言,我会使用(假设
property1
是一个字符串)


就个人而言,我会使用(假设
property1
是一个字符串)


你可以像下面这样做

public string MyString
{
    get
    {
        if(instance!=null && instance1.property1.Equals("bla"))
        {
            return "bla"; 
        }
        else 
        {
            return String.Empty; 
        }
    }
}

这将首先检查实例是否为null。

您可以执行以下操作

public string MyString
{
    get
    {
        if(instance!=null && instance1.property1.Equals("bla"))
        {
            return "bla"; 
        }
        else 
        {
            return String.Empty; 
        }
    }
}

这将首先检查实例是否为空。

人们通常通过以下三种方式之一处理这种情况。最糟糕的方式(在我看来)是对你看到的每一个引用都心存疑虑,总是用空值来测试它,然后如果你遇到空值,就做一些“事情”。这种方法的问题在于,您经常深陷于某个调用树中,因此您所做的“某事”(如返回“合理的”默认值)不仅可能是分层违规,而且可能会掩盖问题,而不是导致问题被违反