gpt4 book ai didi

c# - 如何使用异步实现 TryDoSomething 模式

转载 作者:行者123 更新时间:2023-12-02 03:32:39 26 4
gpt4 key购买 nike

我经常使用TryDoSomething像这样的模式完全是虚构的示例:

GameContext gameContext;
if (gamesRepository.TryLoadLastGame(out gameContext))
{
// Perform actions with gameContext instance.
}
else
{
// Create a new game or go to home screen or whatever.
}

这允许良好的可读流程,但也允许成功状态 true但是一个空返回值有时对于传达“我能够给你你的东西但它实际上是空的”很有用。

使用 async-await,异步较低的 API“强制”调用 API 做正确的事情并异步工作。然而,没有out参数,此模式不起作用。

如何实现?

我有一个答案,并且正在以问答方式回答,以了解其他人如何看待它。

最佳答案

到目前为止,我已经使用了一个名为 Attempt<T> 的小类。 :

public sealed class Attempt<T>
{
/// <summary>
/// Initializes a new instance of the <see cref="Attempt{T}"/> class.
/// </summary>
public Attempt() { }

/// <summary>
/// Initializes a new instance of the <see cref="Attempt{T}"/> class.
/// </summary>
public Attempt(Exception exception)
{
this.Exception = exception;
}

/// <summary>
/// Initializes a new instance of the <see cref="Attempt{T}"/> class.
/// </summary>
/// <param name="result">The result.</param>
public Attempt(T result)
{
this.Result = result;
this.HasResult = true;
}

/// <summary>
/// Gets the result.
/// </summary>
/// <value>The result.</value>
public T Result { get; private set; }

/// <summary>
/// Determines whether this instance has result.
/// </summary>
/// <returns><c>true</c> if this instance has result; otherwise, <c>false</c>.</returns>
public bool HasResult { get; private set; }

/// <summary>
/// Returns the result with a true or false depending on whether its empty, but throws if there is an exception in the attempt.
/// </summary>
/// <param name="result">The result, which may be null.</param>
/// <returns><c>true</c> if the specified result has a value; otherwise, <c>false</c>.</returns>
/// <exception cref="System.AggregateException">The attempt resulted in an exception. See InnerExceptions.</exception>
public bool TryResult(out T result)
{
if (this.HasResult)
{
result = this.Result;
return true;
}
else
{
if (this.Exception != null)
{
throw new AggregateException("The attempt resulted in an exception. See InnerExceptions.", this.Exception);
}
else
{
result = default(T);
return false;
}
}
}

/// <summary>
/// Gets or sets the exception.
/// </summary>
/// <value>The exception.</value>
public Exception Exception { get; private set; }
}

它在 Try 方法中使用,如下所示:

internal async Task<Attempt<T>> TryReadObjectAsync<T>(string folderName, string fileName)
{
if (String.IsNullOrWhiteSpace(folderName))
throw new ArgumentException("The string argument is null or whitespace.", "folderName");

if (String.IsNullOrWhiteSpace(fileName))
throw new ArgumentException("The string argument is null or whitespace.", "fileName");

try
{
StorageFolder folder = this.StorageFolder;
if (folderName != @"\")
folder = await StorageFolder.GetFolderAsync(folderName);

var file = await folder.GetFileAsync(fileName);
var buffy = await FileIO.ReadBufferAsync(file);

string xml = await buffy.ReadUTF8Async();

T obj = await Evoq.Serialization.DataContractSerializerHelper.DeserializeAsync<T>(xml);

return new Attempt<T>(obj);
}
catch (FileNotFoundException fnfe)
{
// Only catch and wrap expected exceptions.

return new Attempt<T>(fnfe);
}
}

并且像这样被消耗:

DataContractStorageSerializer xmlStorage = new DataContractStorageSerializer(this.StorageFolder);

var readAttempt = await xmlStorage.TryReadObjectAsync<UserProfile>(userName, UserProfileFilename);

try
{
UserProfile user;
if (readAttempt.TryResult(out user))
{
// Do something with user.
}
else
{
// No user in the persisted file.
}
}
catch (Exception ex)
{
// Some unexpected, unhandled exception happened.
}

或者,忽略错误。

...
var readAttempt = await xmlStorage.TryReadObjectAsync<UserProfile>(userName, UserProfileFilename);

if (readAttempt.HasResult)
{
// Continue.

this.DoSomethingWith(readAttempt.Result);
}
else
{
// Create new user.
}

关于c# - 如何使用异步实现 TryDoSomething 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23891334/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com