在运行时确定是否允许强制转换(C#)

在运行时确定是否允许强制转换(C#),c#,reflection,casting,C#,Reflection,Casting,我有一个C#wrapper类,它有一系列接受各种数据类型的方法: public class MyClass { public void ProcessString(string Value) { // implementation } public void ProcessInt(int? Value) { // implementation }\ public void ProcessOther(MyClass Value) { // implementation }

我有一个C#wrapper类,它有一系列接受各种数据类型的方法:

public class MyClass
{
    public void ProcessString(string Value) { // implementation }
    public void ProcessInt(int? Value) { // implementation }\
    public void ProcessOther(MyClass Value) { // implementation }
}
现在,我想添加一个通用的
ProcessObject()
方法,以避免在调用相关的流程方法之前显式强制转换对象:

public void ProcessObject(object Value)
{
    if (CanCastToString(Value)
    {
        ProcessString((string)Value);
    }
    else if (CanCastToInt(Value))
    {
        ProcessInt((int?)Value);
    }
    // etc...
}
问题是我不知道我的
CanCastToInt
方法应该是什么-我需要这些方法能够变得健壮,并处理诸如可空类型和其他用户定义的强制转换之类的事情

我该怎么做?我只想知道给定对象是否可以转换为给定类型,即是否:

(SomeType)Value

将工作。

您需要的
操作员
CanCastToString(x)
->
x是字符串

您需要
is
运算符
CanCastToString(x)
->
x是字符串

通常有两种主要方法:

if (Value is SomeType)
{
    // Do something with a cast
}

使用结构或内部类型时,使其可为空:

var v = Value as int?;
if (v != null)
{
    ProcessInt(v.Value);
}

这通常有两种主要方式:

if (Value is SomeType)
{
    // Do something with a cast
}

使用结构或内部类型时,使其可为空:

var v = Value as int?;
if (v != null)
{
    ProcessInt(v.Value);
}

为什么不直接公开处理API,为各种参数提供重载

public class MyClass
{
    public void Process(string Value) { // implementation }
    public void Process(int Value) { // implementation }\
    public void Process(MyClass Value) { // implementation }
    public void Process(object Value) { // catch all method. Handle unknown entities, e.g. call ToString() }
}
编辑使用一些泛型魔法,您可以有一个单一的接口方法、一组完成工作的助手方法和一个处理角落案例的“一网打尽”方法

public class MyClass
{
    void DoProcess(string Value) { // implementation }
    void DoProcess(int Value) { // implementation }\
    void DoProcess(MyClass Value) { // implementation }
    void DoProcess(object Value) { 
        // catch all method. Handle unknown entities, e.g. call ToString()
    }
    public void Process<T>(T value) {
       //this method will call the right overload of DoProcess depending on the compile time type of value. If there isn't a match, it goes to DoProcess(object)
       DoProcess(value);
    }
}

我建议你读一读埃里克·利珀特(Eric Lippert)关于表现型演员的文章。希望在这样做之后,您会意识到为每个受支持的类型设置重载可能会更容易。此外,您可能会意识到,处理解装箱值类型可能是一条地狱之路。

为什么不直接公开处理API,并为各种参数提供重载

public class MyClass
{
    public void Process(string Value) { // implementation }
    public void Process(int Value) { // implementation }\
    public void Process(MyClass Value) { // implementation }
    public void Process(object Value) { // catch all method. Handle unknown entities, e.g. call ToString() }
}
编辑使用一些泛型魔法,您可以有一个单一的接口方法、一组完成工作的助手方法和一个处理角落案例的“一网打尽”方法

public class MyClass
{
    void DoProcess(string Value) { // implementation }
    void DoProcess(int Value) { // implementation }\
    void DoProcess(MyClass Value) { // implementation }
    void DoProcess(object Value) { 
        // catch all method. Handle unknown entities, e.g. call ToString()
    }
    public void Process<T>(T value) {
       //this method will call the right overload of DoProcess depending on the compile time type of value. If there isn't a match, it goes to DoProcess(object)
       DoProcess(value);
    }
}
我建议你读一读埃里克·利珀特(Eric Lippert)关于表现型演员的文章。希望在这样做之后,您会意识到为每个受支持的类型设置重载可能会更容易。此外,您可能会意识到,处理解装箱值类型可能是一条通往地狱的路。

如果(与OP不同)您在运行时之前不知道所涉及的类型,您可以尝试采用以下一些变体:

如果(与OP不同),您在运行时之前不知道所涉及的类型,您可以尝试采用以下一些变体:


不起作用。考虑<代码> x>代码>是<代码>可空< /COD>,然后<代码> x是int < /C> >返回false,但是<代码>(int)x>代码>运行良好。@ Kragen:您确定吗?假设表达式的编译时类型为Nullable。然后您不需要“is”操作符,因为您已经知道对象的确切类型。假设表达式不是可为null的编译时类型。可能是什么类型的?一定是盒装的东西。没有装箱的可为null的int!一个可空的int,要么是空引用,要么是装箱的int(对你来说是个谜:我的分析不完全正确。我错过了什么情况?)不起作用。考虑代码< > x>代码>是一个<代码>可忽略的< /代码>,然后<代码> x是int 返回false,但是<代码>(int)x>代码>工作得很好。@ Kragen:你确定吗?假设表达式的编译时类型为Nullable。然后您不需要“is”操作符,因为您已经知道对象的确切类型。假设表达式不是可为null的编译时类型。可能是什么类型的?一定是盒装的东西。没有装箱的可为null的int!一个可为null的int可以是一个null引用框,也可以是一个已装箱的int。(对你来说是一个难题:我的分析不完全正确。我遗漏了什么情况?)你关心表示形式的转换吗?也就是说,假设您的对象中有一个短框。你想把它转换成int吗?您不能直接将盒装短码转换为int;您必须先将其转换为int,然后再转换为short。你可能想阅读我关于这个主题的文章,以确保你理解这里发生的事情:它们必须是装箱的值类型吗?通常,OO实现这一点的方法是使用每个类型继承的流程方法创建一个接口,然后只调用对象上的方法,而不必担心它是什么类型。您关心表示形式的更改吗?也就是说,假设您的对象中有一个短框。你想把它转换成int吗?您不能直接将盒装短码转换为int;您必须先将其转换为int,然后再转换为short。你可能想阅读我关于这个主题的文章,以确保你理解这里发生的事情:它们必须是装箱的值类型吗?通常情况下,OO的方法是创建一个接口,其中包含一个流程方法,每个类型都继承该方法,然后对对象调用该方法,而不必担心它是什么类型。我已经说过了,但我还想公开一个使用对象的泛型方法,因为它使其他地方的事情变得更简单。我已经说过,但我还想公开一个使用对象的通用方法,因为它使其他地方的事情变得更容易。