使用异常通知委托未设置-设计不良
本文关键字:设置 不良 异常 通知 | 更新日期: 2023-09-27 18:01:17
我创建了一个文档类,用于下载并读取其中的文本。聪明之处在于,它只在需要时下载并读取文档中的文本。通过使用Text属性,它将尝试读取文档,如果它还没有被下载,它将下载然后读取它。
它很好。然而,我注意到我使用异常导致一些时髦的代码。见下文.
文档类
public delegate byte[] DownloadBinaryDelegate(IDocument document);
public delegate string TextReaderDelegate(IDocument document);
public class Document
{
public DownloadBinaryDelegate DownloadBinaryDelegate { private get; set; }
public TextReaderDelegate TextReaderDelegate { private get; set; }
private bool _binaryIsSet;
private byte[] _binary;
public byte[] Binary
{
get
{
if (_binaryIsSet)
return _binary;
if (DownloadBinaryDelegate == null)
throw new NullReferenceException("No delegate attached to DownloadBinaryDelegate.");
Binary = DownloadBinaryDelegate(this);
DownloadBinaryDelegate = null; // unhock delegate as it's no longer needed.
return _binary;
}
set
{
if (_binaryIsSet)
return;
_binary = value;
_binaryIsSet = true;
}
}
private bool _textIsSet;
private string _text;
public string Text
{
get
{
if (_textIsSet)
return _text;
if (TextReaderDelegate == null)
throw new NullReferenceException("No delegate attached to TextReaderDelegate.");
Text = TextReaderDelegate(this); // this delegate will call Binary and return the translated text.
TextReaderDelegate = null; // unhock delegate as it's no longer needed.
return _text;
}
set
{
if (_textIsSet)
return;
_text = value;
_textIsSet = true;
}
}
我一开始写的东西。
if (document.Text == null) // text is not set
{
if (document.Binary == null) // binary has not been downloaded
document.DownloadBinaryDelegate = Util.DownloadDocument;
document.TextReaderDelegate = Util.ReadDocument;
}
完全忘记了Text属性会抛出异常。所以我必须写这样的东西,这是一个有点奇怪的代码。
// check if text has already been read and set
try
{
var isTextSet = document.Text == null;
}
catch (NullReferenceException)
{
document.DownloadBinaryDelegate = Util.DownloadDocument;
document.TextReaderDelegate = Util.ReadDocument;
}
希望你能明白我的意思。
所以我的问题是,这是一个糟糕的设计吗?你会怎么做?请记住,我仍然喜欢当前的功能。延迟初始化已经融入。net框架。我建议使用Lazy<T>
重新实现您的类。
要回答您的具体问题,听起来您的类将始终需要二进制和文本委托,所以我将它们设置为构造函数的必需参数。
我无法使用Lazy,因为我正在使用delegate(this),这是不允许的。
所以我最终使用了这里的好答案:当属性不能为空时使用什么异常类型?
public class Document
{
private DownloadBinaryDelegate _downloadBinaryDelegate;
public void SetDownloadBinaryDelegate(DownloadBinaryDelegate downloadBinary)
{
if (downloadBinary == null)
throw new ArgumentNullException("downloadBinary");
_downloadBinaryDelegate = downloadBinary;
}
private TextReaderDelegate _textReaderDelegate;
public void SetTextReaderDelegate(TextReaderDelegate readerDelegate)
{
if (readerDelegate == null)
throw new ArgumentNullException("readerDelegate");
_textReaderDelegate = readerDelegate;
}
private bool _binaryIsSet;
private byte[] _bytes;
public void SetBinary(byte[] bytes, bool forceOverwrite = false)
{
if (_binaryIsSet && !forceOverwrite)
return;
_bytes = bytes;
_binaryIsSet = true;
}
public byte[] GetBinary()
{
if (_binaryIsSet)
return _bytes;
if (_downloadBinaryDelegate == null)
throw new InvalidOperationException("No delegate attached to DownloadBinaryDelegate. Use SetDownloadBinaryDelegate.");
SetBinary(_downloadBinaryDelegate(this));
_downloadBinaryDelegate = null; // unhock delegate as it's no longer needed.
return _bytes;
}
public bool TryGetBinary(out byte[] bytes)
{
if (_binaryIsSet)
{
bytes = _bytes;
return true;
}
if (_downloadBinaryDelegate != null)
{
bytes = GetBinary(); // is this legit?
return true;
}
bytes = null;
return false;
}
private bool _textIsSet;
private string _text;
public void SetText(string text, bool forceOverwrite = false)
{
if (_textIsSet && !forceOverwrite)
return;
_text = text;
_textIsSet = true;
}
public string GetText()
{
if (_textIsSet)
return _text;
if (_textReaderDelegate == null)
throw new InvalidOperationException("No delegate attached to TextReaderDelegate. Use SetTextReaderDelegate.");
SetText(_textReaderDelegate(this)); // this delegate will call Binary and return the read text.
_textReaderDelegate = null; // unhock delegate as it's no longer needed.
return _text;
}
public bool TryGetText(out string text)
{
byte[] bytes;
if (!TryGetBinary(out bytes))
{
text = null;
return false;
}
if (_textIsSet)
{
text = _text;
return true;
}
if (_textReaderDelegate != null)
{
text = GetText(); // is this legit?
return true;
}
text = null;
return false;
}
}