从泛型对象类型参数中排除类型



我有一个重载的单选按钮扩展方法,它会中断运行时的执行。在某些情况下,第一个方法的参数可能会与第二个方法的自变量混淆,反之亦然。

public static MvcHtmlString MyRadioButton<TModel>( this HtmlHelper<TModel> helper, string property_name, string value, bool is_checked, string label = "", object attributes = null, bool separate_label = false, bool within_div = true, bool label_after = true )
{
// method implementation
}

和过载:

public static MvcHtmlString MyRadioButton<TModel>( this HtmlHelper<TModel> helper, string property_name, string value, bool is_checked, object attributes = null, bool separate_label = false, bool within_div = true, bool label_after = true )
{
return MyRadioButton(helper, property_name, value, is_checked, "", attributes, separate_label, within_div, label_after);
}

在这种情况下:

Html.MyRadioButton("name", "value", true, "");

空字符串作为对象类型"attributes"参数和字符串类型"label"参数都有效,从而导致方法之间的冲突。

有没有一种方法可以泛型地键入一个参数,然后在方法中从该定义中排除类型?我想可能是对象类型的继承类,它接受要排除的类型列表,比如object<string>。另一种解决方案是混淆重载的参数,这样就可以清楚地知道需要调用哪个,但这远不如正确键入参数优雅。

由于空字符串可以是stringobject,因此在调用时可以通过指定名称来区分是希望空字符串作为label还是attributes传递:

Html.MyRadioButton("name", "value", true, label: "")
Html.MyRadioButton("name", "value", true, attributes: "")

为什么会过载?只需将一个方法内部委托给适当的实现,该实现定义了label的默认值,允许您辨别消费者想要什么选项。

public static MvcHtmlString MyRadioButton<TModel>(this HtmlHelper<TModel> helper,
string property_name,
string value,
bool is_checked,
string label = null, //general case
object attributes = null,
bool separate_label = false,
bool within_div = true,
bool label_after = true )
{
if (label == null)
return myImplentationWithLabelNotDefined( //all arguments//);
return myImplementationWithLabelDefined(//all arguments//);
}

您甚至可以将helper方法定义为内部函数,以避免参数混乱。。。

也许一个简单的解决方案,比如创建一个特殊的字符串类,可以比使用generic type constraint做得更好

[更新]
这是我的建议:

public class MySpecialString
{
public string MyStringl;
public MySpecialString(string txt)
{
this.MyStringl = txt;
}
}
public class MyAttributes
{
public MyAttributes()
{
}
}
public static class Extentions
{
public static MvcHtmlString MyRadioButton<TModel>(this HtmlHelper<TModel> helper, string property_name,
string value, bool is_checked, MySpecialString mystring = null , object attributes = null, bool separate_label = false,
bool within_div = true, bool label_after = true)
{
// method implementation
}
public static MvcHtmlString MyRadioButton<TModel>(this HtmlHelper<TModel> helper, string property_name,
string value, bool is_checked, MyAttributes attributes = null, bool separate_label = false,
bool within_div = true, bool label_after = true)
{
// method implementation
}
}

如果attributes参数用于POCO,而不是值类型(例如从不使用字符串、整数、布尔值等(,则可以执行以下操作:

public static MvcHtmlString MyRadioButton<TModel, T>( 
this this HtmlHelper<TModel>, ...,
T attributes,
... // omitted for brevity
) where T: new() // <- IMPORTANT LINE
{ 
// etc...
}
// which can be used with any anonymous or structured object:
helper.MyRadioButton(new { attribute1 = "hello world" }); 
helper.MyRadioButton(new MyClass());
// but not value types:
helper.MyRadioButton("this won't work for the above overload");

我希望添加一个通用约束就足以让运行时"更好地了解"这是否与您的用例相匹配。


如果仅将其用于POCO,我将以任何一种方式添加约束。这样就不必担心意外传入值类型。

更新

有没有一种方法可以泛型地键入一个参数,然后在构造函数中从该定义中排除类型?

我在最初的回答中回避了这个问题。使用where约束,可以将传递的类型限制为一个类型,但不能指定要排除的类型。有关更多详细信息,请参阅类型参数约束语言规范和文档。

最新更新