C# 确保对象不为null
如何确保类的某个实例永远不会为null?有人告诉我使用Debug.Assert(),但这样做,我只会确保代码在调试模式下工作,而我想确保发布版中的条件永远不为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,则会引发异常。我希望今后避免犯这样的错误,避
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; }
}
在我的示例类型中,我要求我的名
和姓
值具有非空值。这是通过我的构造函数强制执行的。。。myPerson
类型永远不能用空值进行实例化(尽管,空值可能同样糟糕,因此检查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; }
}
MyPerson
类型仍然强制执行操作所需的字段,但引入了可选字段。然后,在执行使用这些成员的操作时,我需要考虑这一点:
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; }
}
在我的示例类型中,我要求我的名
和姓
值具有非空值。这是通过我的构造函数强制执行的。。。myPerson
类型永远不能用空值进行实例化(尽管,空值可能同样糟糕,因此检查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; }
}
MyPerson
类型仍然强制执行操作所需的字段,但引入了可选字段。然后,在执行使用这些成员的操作时,我需要考虑这一点:
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;
}
}
}
这将首先检查实例是否为空。人们通常通过以下三种方式之一处理这种情况。最糟糕的方式(在我看来)是对你看到的每一个引用都心存疑虑,总是用空值来测试它,然后如果你遇到空值,就做一些“事情”。这种方法的问题在于,您经常深陷于某个调用树中,因此您所做的“某事”(如返回“合理的”默认值)不仅可能是分层违规,而且可能会掩盖问题,而不是导致问题被违反