Сравнительные тесты Производительности
Catch exception:
10,000 good: 63,668 ticks
10,000 bad: 6,435,609 ticks
Regex Pre-Screen:
10,000 good: 637,633 ticks
10,000 bad: 717,894 ticks
COM Interop CLSIDFromString
10,000 good: 126,120 ticks
10,000 bad: 23,134 ticks
Межглавный (Самый Быстрый) Ответ COM:
/// <summary>
/// Attempts to convert a string to a guid.
/// </summary>
/// <param name="s">The string to try to convert</param>
/// <param name="value">Upon return will contain the Guid</param>
/// <returns>Returns true if successful, otherwise false</returns>
public static Boolean TryStrToGuid(String s, out Guid value)
{
//ClsidFromString returns the empty guid for null strings
if ((s == null) || (s == ""))
{
value = Guid.Empty;
return false;
}
int hresult = PInvoke.ObjBase.CLSIDFromString(s, out value);
if (hresult >= 0)
{
return true;
}
else
{
value = Guid.Empty;
return false;
}
}
namespace PInvoke
{
class ObjBase
{
/// <summary>
/// This function converts a string generated by the StringFromCLSID function back into the original class identifier.
/// </summary>
/// <param name="sz">String that represents the class identifier</param>
/// <param name="clsid">On return will contain the class identifier</param>
/// <returns>
/// Positive or zero if class identifier was obtained successfully
/// Negative if the call failed
/// </returns>
[DllImport("ole32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = true)]
public static extern int CLSIDFromString(string sz, out Guid clsid);
}
}
<час> Нижняя строка: Если необходимо проверить, является ли строка гуидом, и Вы заботитесь о производительности, используете COM Interop.
, Если необходимо преобразовать гуид в Строковом представлении к Гуиду, используйте
new Guid(someString);
Нет, вы не можете этого сделать. Было бы неплохо, но это невозможно без участия какого-то АОП. Я уверен, что PostSharp может сделать хорошую работу, надеюсь, используя атрибуты, и в Code Contracts это будет просто:
Contract.Requires(qwerty != null);
В идеале мне нужен атрибут PostSharp, который генерирует вызов Code Contracts - и я поиграю с этим в какой-то момент - но до тех пор метод расширения, который у вас есть, - лучший подход, который я нашел ...
(Если я когда-нибудь попробую подход PostSharp + Code Contracts, я обязательно напишу об этом, кстати ... Моно Сесил тоже может сделать это достаточно легко.)
РЕДАКТИРОВАТЬ: Чтобы расширить ответ Лорана, вы потенциально могли бы иметь:
new { qwerty }.CheckNotNull();
И если бы у вас было много параметров, не допускающих значения NULL, вы мог бы иметь:
new { qwerty, uiop, asdfg }.CheckNotNull();
Это должно было бы использовать отражение для определения свойств. Есть способы, которыми вы можете избежать отражения при каждом доступе, создания делегата для каждого свойства и, как правило, неуместного. Я могу исследовать это для сообщения в блоге ... но это несколько неприятно, и я предпочитаю возможность просто атрибутировать параметры ...
РЕДАКТИРОВАТЬ: Код реализован, и сообщение в блоге должным образом сделанный. Крик, но весело
Одним словом: №
В метод расширения передается значение. Он не знает, откуда взялось значение или какой идентификатор мог выбрать вызывающий абонент для его обозначения.
Я считаю, что проще всего сделать это с помощью фрагмента кода.
В вашем примере я могу ввести tna
.
Вот фрагмент:
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Check for null arguments</Title>
<Shortcut>tna</Shortcut>
<Description>Code snippet for throw new ArgumentNullException</Description>
<Author>SLaks</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
<SnippetType>SurroundsWith</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>Parameter</ID>
<ToolTip>Paremeter to check for null</ToolTip>
<Default>value</Default>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[if ($Parameter$ == null) throw new ArgumentNullException("$Parameter$");
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
См. Также ArgumentNullException и рефакторинг для полного решения по тем же принципам, что и ответ.
А как насчет:
public void Save(Category qwerty)
{
ThrowIfArgumentIsNull( () => return qwerty );
qwerty.ThrowIfArgumentIsNull("qwerty");
// ....
}
затем определите ThrowIfArgumentIsNull как
public static void ThrowIfArgumentIsNull(Expression<Func<object>> test)
{
if (test.Compile()() == null)
{
// take the expression apart to find the name of the argument
}
}
извините, у меня нет времени, чтобы заполнить детали или предоставить полный код в настоящее время.
Я бы порекомендовал вам сделать следующее:
public static void ThrowIfArgumentIsNull(this object value, string argument)
{
if (value == null)
{
throw new ArgumentNullException(argument);
}
}
Использование дженериков в этом случае, похоже, не добавляет никакого значения. Но что касается вашего первоначального вопроса, я не думаю, что это возможно.
Мне нравится Применять из общих библиотек Lokad .
Базовый синтаксис:
Enforce.Arguments(() => controller, () => viewManager,() => workspace);
Это вызовет исключение с именем параметра и введите, если какой-либо из аргументов имеет значение NULL.