Я использую кодовые контракты в C # 4.0. Я применяю обычный статический метод цепочки для имитации необязательных параметров (я знаю, что C # 4.0 поддерживает необязательные параметры, но я действительно не хочу их использовать).
Дело в том, что мои контрактные требования выполняются дважды (или, возможно, количество связанных с ними перегрузок, которые я реализую), если я вызываю метод Init(string , string[])
- очевидный эффект из примера исходного кода ниже. Это может быть дорого, особенно из-за относительно дорогих требований, таких как File.Exists
, который я использую.
public static void Init(string configurationPath, string[] mappingAssemblies)
{
// The static contract checker 'makes' me put these here as well as
// in the overload below.
Contract.Requires<ArgumentNullException>(configurationPath != null, "configurationPath");
Contract.Requires<ArgumentException>(configurationPath.Length > 0, "configurationPath is an empty string.");
Contract.Requires<FileNotFoundException>(File.Exists(configurationPath), configurationPath);
Contract.Requires<ArgumentNullException>(mappingAssemblies != null, "mappingAssemblies");
Contract.Requires<FileNotFoundException>(Contract.ForAll<string>(mappingAssemblies, (n) => File.Exists(n)));
Init(configurationPath, mappingAssemblies, null);
}
public static void Init(string configurationPath, string[] mappingAssemblies, string optionalArgument)
{
// This is the main implementation of Init and all calls to chained
// overloads end up here.
Contract.Requires<ArgumentNullException>(configurationPath != null, "configurationPath");
Contract.Requires<ArgumentException>(configurationPath.Length > 0, "configurationPath is an empty string.");
Contract.Requires<FileNotFoundException>(File.Exists(configurationPath), configurationPath);
Contract.Requires<ArgumentNullException>(mappingAssemblies != null, "mappingAssemblies");
Contract.Requires<FileNotFoundException>(Contract.ForAll<string>(mappingAssemblies, (n) => File.Exists(n)));
//...
}
Если, однако, я исключаю требования из этого метода, статическая проверка жалуется, что требования перегрузки Init(string, string[], string)
не выполнены. Я считаю, что статическая проверка не понимает, что требования перегрузки Init(string, string[], string)
неявно применимы и к методу Init(string, string[])
; что-то, что можно было бы вычесть из кода IMO.
Вот такую ситуацию я бы хотел достичь:
public static void Init(string configurationPath, string[] mappingAssemblies)
{
// I don't want to repeat the requirements here because they will always
// be checked in the overload called here.
Init(configurationPath, mappingAssemblies, null);
}
public static void Init(string configurationPath, string[] mappingAssemblies, string optionalArgument)
{
// This is the main implementation of Init and all calls to chained
// overloads end up here.
Contract.Requires<ArgumentNullException>(configurationPath != null, "configurationPath");
Contract.Requires<ArgumentException>(configurationPath.Length > 0, "configurationPath is an empty string.");
Contract.Requires<FileNotFoundException>(File.Exists(configurationPath), configurationPath);
Contract.Requires<ArgumentNullException>(mappingAssemblies != null, "mappingAssemblies");
Contract.ForAll<string>(mappingAssemblies, (n) => File.Exists(n));
//...
}
Итак, мой вопрос таков: есть ли способ автоматически применить требования Init(string, string[], string)
к Init(string, string[])
?
Обновление
Я использовал ForAll
метод неправильно: он предназначен для использования внутри требования или аналогично, например так:
Contract.Requires<FileNotFoundException>(Contract.ForAll<string>(mappingAssemblies, (n) => File.Exists(n)));