![](/img/trans.png)
[英]Best way to check if one of the subelement is null and not throw an exception
[英]The best way to throw an exception
你知道一个比下面更好的方式(更漂亮)抛出异常吗?
public long GetPlaylistId(long songInPlaylistId)
{
var songInPlaylist = service.GetById(songInPlaylistId);
return songInPlaylist
.With(x => x.Playlist)
.ReturnValueOrException(x => x.Id,
new ArgumentException(
"Bad argument 'songInPlaylistId'"));
}
Monadic扩展方法:
public static TResult With<TInput, TResult>(this TInput obj,
Func<TInput, TResult> evaluator)
where TInput : class
where TResult : class
{
return obj == null ? null : evaluator(obj);
}
public static TResult ReturnValueOrException<TInput, TResult>(
this TInput obj, Func<TInput, TResult> evaluator, Exception exception)
where TInput : class
{
if (obj != null)
{
return evaluator(obj);
}
throw exception;
}
如果尝试获取没有播放列表的播放列表是有效的,那么你不应该抛出异常,而应该只返回一个特殊的值,意思是“找不到”(例如,取决于0或-1)关于播放列表ID的工作方式)。
或者,您可以编写一个TryGetPlaylistId()
方法,该方法的工作方式与Microsoft的TryXXX()
方法类似(例如SortedList.TryGetValue()
),例如:
public bool TryGetPlaylistId(long songInPlaylistId, out long result)
{
result = 0;
var songInPlaylist = service.GetById(songInPlaylistId);
if (songInPlaylist == null)
return false;
if (songInPlaylist.Playlist == null)
return false;
result = songInPlaylist.Playlist.Id;
return true;
}
这种方法的一个小问题是,您在模拟诊断问题时可能会使用的信息模糊不清。 也许添加Debug.WriteLine()
或其他形式的日志记录是有用的。 关键是,您无法区分未找到播放列表ID的情况和找到它但不包含播放列表的情况。
否则,您可以抛出一个具有更多信息的异常,例如:
public long GetPlaylistId(long songInPlaylistId)
{
var songInPlaylist = service.GetById(songInPlaylistId);
if (songInPlaylist == null)
throw new InvalidOperationException("songInPlaylistId not found: " + songInPlaylistId);
if (songInPlaylist.Playlist == null)
throw new InvalidOperationException("Playlist for ID " + songInPlaylistId " has no playlist: ");
return songInPlaylist.Playlist.Id;
}
可能的情况是,在播放列表中找不到该歌曲是有效的,但找到没有播放列表的歌曲是无效的,在这种情况下,您将在第一种情况下返回特殊值并抛出异常在第二种情况下,例如:
public long GetPlaylistId(long songInPlaylistId)
{
var songInPlaylist = service.GetById(songInPlaylistId);
if (songInPlaylist == null)
return -1; // -1 means "playlist not found".
if (songInPlaylist.Playlist == null)
throw new InvalidOperationException("Playlist for ID " + songInPlaylistId " has no playlist: ");
return songInPlaylist.Playlist.Id;
}
无论如何,我个人认为你的扩展方法只是模糊了代码。
try{
if (obj != null)
{
return evaluator(obj);
}
}
catch(Exception ex)
{
throw;
}
返回obj;
除非陷入某些人,否则你不应该抛出错误。 最好在给定的情况下返回null并在您的调用代码中处理它:
如果我班上有多个这样模棱两可的方法,会发生什么? 为任何方法制定不同的规则是非常困难的。 最后你会感到困惑。 您对此解决方案有何看法?
public class ApplicationResponse
{
public IList<string> Errors { get; set; }
public dynamic Data { get; set; }
public bool HasErrors()
{
return Errors != null && Errors.Any();
}
}
public ApplicationResponse GetPlaylistId(long songInPlaylistId)
{
var songInPlaylist = service.GetById(songInPlaylistId);
if (songInPlaylist == null)
{
return new ApplicationResponse { Errors = new[] { "Song was not found." } };
}
if (songInPlaylist.Playlist == null)
{
return new ApplicationResponse { Errors = new[] { "Playlist was not found." } };
}
return new ApplicationResponse { Data = songInPlaylist.Playlist.Id };
}
public HttpResponseMessage SomeRequest([FromUri] songInPlaylistId)
{
var response = appService.GetPlaylistId(long songInPlaylistId);
if (response.HasErrors())
{
// reply with error status
}
// reply with ok status
}
在这种情况下,我可以将所有错误发送给客户端。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.