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

时间:2010-06-23 01:39:48

标签: c# reflection casting

我有一个C#wraper类,其中包含一系列接受各种数据类型的方法:

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

会工作。

5 个答案:

答案 0 :(得分:4)

通常有两种主要方式:

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

var v = Value as SomeType;
if (v != null)
{
    // Value was successfully cast as SomeType
}

使用结构体或内部类型时,请将它们设为可为空:

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

答案 1 :(得分:1)

您需要is运营商。 CanCastToString(x) - > x is string

答案 2 :(得分:1)

为什么不直接公开您的处理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);
    }
}

这样可以避免对基本类型进行装箱,并且类型安全性稍好一些。

对于全能方法,您可以尝试使用Type.IsAssignableFrom方法。例如:

if (typeof(short).IsAssignableFrom(Value)
    DoProcess((short)Value);
if (typeof(byte).IsAssignableFrom(Value)
    DoProcess((byte)Value);

我建议您阅读Eric Lippert关于代表性演员的文章。希望在执行此操作之后,您将意识到每个受支持的类型都可能更容易过载。此外,您可能会意识到处理拆箱值类型可能是通往地狱的道路。

答案 3 :(得分:1)

如果(与OP不同?)您不知道运行时所涉及的类型,您可能会尝试使用其中的一些变体:

http://codegoeshere.blogspot.com/2007/05/dynamic-cast-in-c.html

答案 4 :(得分:-1)

    public void QuickTest()
    {
        object stringObj = "string";
        object nullableInt1 = (int?)null;
        object nullableInt2 = (int?)1;
        object decimalObj = 1.5m;

        ProcessObject(stringObj);
        ProcessObject(nullableInt1);
        ProcessObject(nullableInt2);
        ProcessObject(decimalObj);
    }

    public void ProcessObject(object value)
    {
        if (value == null)
        {
            Debug.WriteLine("null");
            return;
        }


        if (value is string)
        {
            Debug.WriteLine((string)value);
            return;
        }

        string stringValue = value.ToString();

        int intTemp;
        if (int.TryParse(stringValue, out intTemp))
        {
            Debug.WriteLine(intTemp);
            return;
        }

        decimal decimalTemp;
        if (decimal.TryParse(stringValue, out decimalTemp))
        {
            Debug.WriteLine(decimalTemp);
            return;
        }
        // etc...
    }