Je pensais à un bon objet d'exception générique qui remplacerait throw new Exception(string.Format("...",...))
, à la fois pour simplifier et aussi pour accélérer de tels objets. Le formatage lent String.Format()
doit être différé jusqu'à ce que la propriété Message
soit appelée. La sérialisation est également quelque peu risquée. En outre, un tel objet pourrait ultérieurement implémenter la localisation.FormattedException au lieu de lancer new Exception (string.Format (...)) dans .NET
Mise à jour: Cette exception doit être héritée par des exceptions utilisateur plus spécifiques, et non par elle-même. Désolé de ne pas être clair.
Voici ce que j'ai trouvé. S'il vous plaît commenter s'il y a des moyens de l'améliorer. Merci!
/// <summary>
/// Generic exception capable of delayed message formatting.
/// Inherit for more specific exceptions.
/// </summary>
[Serializable]
public class FormattedException : Exception
{
private readonly object[] _arguments;
private readonly string _formatStr;
private readonly bool _useFormat;
private FormattedException(bool useFormat, Exception inner, string message, params object[] args)
: base(message, inner)
{
_useFormat = useFormat;
_formatStr = message;
_arguments = args;
}
public FormattedException()
: this(false, null, null, null)
{}
public FormattedException(string message)
: this(false, null, message, null)
{}
public FormattedException(string message, params object[] args)
: this(true, null, message, args)
{}
public FormattedException(Exception inner, string message)
: this(false, inner, message, null)
{}
public FormattedException(Exception inner, string message, params object[] args)
: this(true, inner, message, args)
{}
public override string Message
{
get
{
if (!_useFormat)
return _formatStr;
try
{
return string.Format(_formatStr, _arguments);
}
catch (Exception ex)
{
var sb = new StringBuilder();
sb.Append("Error formatting exception: ");
sb.Append(ex.Message);
sb.Append("\nFormat string: ");
sb.Append(_formatStr);
if (_arguments != null && _arguments.Length > 0)
{
sb.Append("\nArguments: ");
for (int i = 0; i < _arguments.Length; i++)
{
if (i > 0) sb.Append(", ");
try
{
sb.Append(_arguments[i]);
}
catch (Exception ex2)
{
sb.AppendFormat("(Argument #{0} cannot be shown: {1})", i, ex2.Message);
}
}
}
return sb.ToString();
}
}
}
#region Serialization
private const string SerializationField = "FormatString";
protected FormattedException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
_formatStr = (string) info.GetValue(SerializationField, typeof (string));
// Leave other values at their default
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
// To avoid any serialization issues with param objects, format message now
info.AddValue(SerializationField, Message, typeof (string));
}
#endregion
}
Vous êtes préoccupé par la performance de string.Format() en lançant une exception? À quelle fréquence prévoyez-vous des exceptions? – Henrik
Le vrai "problème", il semble que vous essayez de résoudre est que String.Format représente 13 caractères de fouillis visuel ennuyeux. C'est le cas, mais si vous trouvez cela gênant, vous devez définir une méthode statique privée qui s'y accole. Je ne suggérerais pas de différer le format jusqu'à ce que l'exception soit vue, car il n'y a aucune garantie que tous les objets mutables auxquels l'exception détient une référence n'auront pas changé d'ici là. – supercat