C# 不必要的NullReferenceException?
为什么在下面的代码中会出现C# 不必要的NullReferenceException?,c#,C#,为什么在下面的代码中会出现NullReferenceException private string FileR ( string name ) { string[] content = ReadSite(name, Protocol.read, url); Request_Template newCon; string[] final = new string[content.Length]; for (int i = 0; i < content.Le
NullReferenceException
private string FileR ( string name )
{
string[] content = ReadSite(name, Protocol.read, url);
Request_Template newCon;
string[] final = new string[content.Length];
for (int i = 0; i < content.Length; i++)
{
if (content[i].Equals(null))
{
return "content [" + i + "] returns null";
}
newCon = JsonSerializer.Deserialize<Request_Template>(content[i]);
if (newCon.Sender.Contains(myAccount.Username))
{
newCon.Sender = "Me";
}
string sender = newCon.Sender;
string message = newCon.Message;
final[i] = sender + ":\t" + message;
}
string nFinal = string.Concat(final);
Thread.Sleep(10);
return nFinal;
}
string[] ReadSite(string filename, Protocol p, string uri)
{
Read_Template temp = new Read_Template
{
Chat = filename,
Code = key1
};
string myUrl = JsonSerializer.Serialize(temp);
WebClient web = new WebClient();
Stream stream = web.OpenRead(uri + "/" + myUrl);
int length = 0;
while (new StreamReader(stream).ReadLine() != null)
{
length++;
}
string[] content = new string[length];
using (StreamReader reader = new StreamReader(stream))
{
for (int i = 0; i < length; i++)
{
content[i] = reader.ReadLine();
}
}
return content;
}
专用字符串文件管理器(字符串名称)
{
string[]content=ReadSite(名称、Protocol.read、url);
请求模板newCon;
string[]final=新字符串[content.Length];
for(int i=0;i
我尝试过使用调试工具,但没有效果。当我运行代码时,它说错误来自string[]final=newstring[content.Length];
和for(int i=0;i
。这导致我假设内容
为空。但是当我使用watch窗口时,它说变量content
无法确定。如何解决此问题?我强烈怀疑问题实际上在这里:
if(content[i].Equals(null))
如果content[i]
确实为null,那么调用content[i].Equals
将抛出NullReferenceException
。该测试应写成:
如果(内容[i]为空)`
或(对于6岁或以上的儿童):
if(内容[i]==null)`
现在,如果ReadSite
中没有bug,那么您根本不需要该检查,因为ReadSite
应该返回一个非空字符串引用数组。但是,填充数组的方式被破坏了。您目前:
- 围绕流创建
StreamReader
- 从读卡器读取数据,直到数据用完
- 创建长度为“右”的新数组
- 围绕同一个流创建另一个
,现在已经结束StreamReader
- 从读者那里阅读无论你最初读了多少遍一行
ReadLine()
将在每次迭代中返回null
相反,您应该只阅读一次,边阅读边填充列表,如下所示:
列表内容=新列表();
使用(var stream=web.OpenRead(uri+“/”+myUrl))
{
使用(变量读取器=新的流读取器(流))
{
弦线;
而((line=reader.ReadLine())是对象)
{
内容。添加(行);
}
}
}
返回内容;
这将返回一个列表
,因此您需要将读取站点
返回类型更改为列表
,或者可能是IReadOnlyList
。如果确实需要它来返回数组,则可以返回content.ToArray()
(理想情况下,也可以使用HttpClient
,但情况不同。)私有字符串文件管理器(字符串名称)
{
//ReadSite始终返回长度为0或更长的内容。字符串[]内容永远不会等于null。
//测试:字符串[]测试=新字符串[0];测试==null->False
string[]content=ReadSite(名称、Protocol.read、url);
请求模板newCon;
string[]final=新字符串[content.Length];
//如果content.Length==0,此循环将永远不会发生,并且您将不会得到任何NRE。
for(int i=0;i
在有问题的行中放置断点(F9),然后再次运行;你能从远程地址收到一个错误吗?你从哪里得到一个NullReferenceException?回答很好,你花了很长时间来解释一切,给我留下了深刻的印象。“我不相信你会在这里得到一个错误”-wh
private string FileR ( string name )
{
// ReadSite always returns a content that has length 0 or more. string[] content will never equals null.
// TEST: string[] test = new string[0]; test == null -> False
string[] content = ReadSite(name, Protocol.read, url);
Request_Template newCon;
string[] final = new string[content.Length];
// if content.Length == 0, this loop will never occur and you wont get any NREs.
for (int i = 0; i < content.Length; i++)
{
// It is highly unlikely that a reader.ReadLine() would generate a null but
// just in case it does, use == null instead of .Equals() method. When content[i] == null, you cannot use .Equals() method since nulls dont have Equals method.
if (content[i].Equals(null))
{
return "content [" + i + "] returns null";
}
// If you have checked that content[i] is Not empty space or null, you might
//end up with newCon == null if Deserialization fails. Cover this around try / catch.
newCon = JsonSerializer.Deserialize<Request_Template>(content[i]);
// If deserialization fails, this will throw NRE because nulls wont have
// Sender as a property or array. Check if newCon == null or not. Also,
// check if Sender was correctly initialized as an array/list.. as it could
// be null. nulls wont have Contains as a method.
if (newCon.Sender.Contains(myAccount.Username))
{
newCon.Sender = "Me";
}
string sender = newCon.Sender;
string message = newCon.Message;
// This should work correctly as its dependent on content.length. If the
// loop is happening, then there is at least one final element that can be updated.
final[i] = sender + ":\t" + message;
}
string nFinal = string.Concat(final);
Thread.Sleep(10);
return nFinal;
}