基础构造函数调用中的 Lambda
Lambdas in Base Constructor Call
好的,所以我有以下基础class:
public partial class InputValidator<T> : UserControl {
public InputValidator(TryParse<T> parserMethod, T initialValue) { }
public T Value { get; set; }
public bool IsInputValid { get; }
public override string Text { get; set; }
public string InputInvalidMessage { get; set; }
public TryParse<T> Parser { get; set; }
}
其中 TryParse<T>
是代表一种方法的委托,类似于内置类型的所有 TryParse
方法。
public delegate bool TryParse<T>(string input, out T result);
上面的class是一个文本输入控件,它尝试使用指定的解析方法来解析用户输入,当它无法解析输入时,它会在文本框下方显示一条消息,指出用户的输入无效。
我现在有以下来自这个 class:
public class StructInputValidator<T> : InputValidator<T?> where T : struct
{
public StructInputValidator(TryParse<T> parser, T? initialValue)
: base((string text, out T? result) => {
T nonNullableResult;
bool parseSuccessful = parser(text, out nonNullableResult);
if (!parseSuccessful) result = null;
else result = nonNullableResult;
return parseSuccessful;
},
initialValue) { }
}
上面的 class 将一个不可为 null 的结构作为其类型参数,并派生自 InputValidator<T?>
。此派生的 class 的目的是为不可空结构采用 TryParse 方法,并为相应的可空结构提供输入验证器控件,这样当输入无效时,值 属性 将被设置为空。它这样做的方式是在构造函数中接受一个 TryParse 委托,然后将类型为 TryParse 的 lambda 表达式传递给基础 class 构造函数。
如您所见,将 TryParse<T>
委托转换为 TryParse<T?>
委托所需的 lambda 表达式的长度足以在调用基本构造函数时变得非常丑陋。
我的问题是:在像这样调用基本构造函数时有 lambda 表达式的场景中,什么被认为是标准 "best practice"? 我可以不要传入使用解析器 属性 的实例方法,因为基础构造函数在初始化 属性 之前运行。我无法传入采用不可为 null 的 TryParse<T>
委托的静态方法,因为这样它的签名将与 TryParse<T?>
的签名不匹配。
是的,这不太好...但是您可以使用辅助方法,如下所示:
public class StructInputValidator<T> : InputValidator<T?> where T : struct
{
public StructInputValidator(TryParse<T> parser, T? initialValue)
: base(ToNullableTryParse(parser), initialValue)
{ }
private static TryParse<T?> ToNullableTryParse(TryParse<T> parser)
{
return (string text, out T? result) => {
T nonNullableResult;
bool parseSuccessful = parser(text, out nonNullableResult);
result = parseSuccessful ? (T?)nonNullableResult : null;
return parseSuccessful;
};
}
}
编写一个作为实现的静态方法,并从您的 lambda 中调用它:
public static bool InvokeParser(string text, out T? result, TryParse<T> parser)
{
T nonNullableResult;
bool parseSuccessful = parser(text, out nonNullableResult);
if (!parseSuccessful) result = null;
else result = nonNullableResult;
return parseSuccessful;
}
public StructInputValidator(TryParse<T> parser, T initialValue)
: base((string text, out T? result) => InvokeParser(text, out result, parser),
initialValue) { }
好的,所以我有以下基础class:
public partial class InputValidator<T> : UserControl {
public InputValidator(TryParse<T> parserMethod, T initialValue) { }
public T Value { get; set; }
public bool IsInputValid { get; }
public override string Text { get; set; }
public string InputInvalidMessage { get; set; }
public TryParse<T> Parser { get; set; }
}
其中 TryParse<T>
是代表一种方法的委托,类似于内置类型的所有 TryParse
方法。
public delegate bool TryParse<T>(string input, out T result);
上面的class是一个文本输入控件,它尝试使用指定的解析方法来解析用户输入,当它无法解析输入时,它会在文本框下方显示一条消息,指出用户的输入无效。
我现在有以下来自这个 class:
public class StructInputValidator<T> : InputValidator<T?> where T : struct
{
public StructInputValidator(TryParse<T> parser, T? initialValue)
: base((string text, out T? result) => {
T nonNullableResult;
bool parseSuccessful = parser(text, out nonNullableResult);
if (!parseSuccessful) result = null;
else result = nonNullableResult;
return parseSuccessful;
},
initialValue) { }
}
上面的 class 将一个不可为 null 的结构作为其类型参数,并派生自 InputValidator<T?>
。此派生的 class 的目的是为不可空结构采用 TryParse 方法,并为相应的可空结构提供输入验证器控件,这样当输入无效时,值 属性 将被设置为空。它这样做的方式是在构造函数中接受一个 TryParse 委托,然后将类型为 TryParse 的 lambda 表达式传递给基础 class 构造函数。
如您所见,将 TryParse<T>
委托转换为 TryParse<T?>
委托所需的 lambda 表达式的长度足以在调用基本构造函数时变得非常丑陋。
我的问题是:在像这样调用基本构造函数时有 lambda 表达式的场景中,什么被认为是标准 "best practice"? 我可以不要传入使用解析器 属性 的实例方法,因为基础构造函数在初始化 属性 之前运行。我无法传入采用不可为 null 的 TryParse<T>
委托的静态方法,因为这样它的签名将与 TryParse<T?>
的签名不匹配。
是的,这不太好...但是您可以使用辅助方法,如下所示:
public class StructInputValidator<T> : InputValidator<T?> where T : struct
{
public StructInputValidator(TryParse<T> parser, T? initialValue)
: base(ToNullableTryParse(parser), initialValue)
{ }
private static TryParse<T?> ToNullableTryParse(TryParse<T> parser)
{
return (string text, out T? result) => {
T nonNullableResult;
bool parseSuccessful = parser(text, out nonNullableResult);
result = parseSuccessful ? (T?)nonNullableResult : null;
return parseSuccessful;
};
}
}
编写一个作为实现的静态方法,并从您的 lambda 中调用它:
public static bool InvokeParser(string text, out T? result, TryParse<T> parser)
{
T nonNullableResult;
bool parseSuccessful = parser(text, out nonNullableResult);
if (!parseSuccessful) result = null;
else result = nonNullableResult;
return parseSuccessful;
}
public StructInputValidator(TryParse<T> parser, T initialValue)
: base((string text, out T? result) => InvokeParser(text, out result, parser),
initialValue) { }