Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在c中,将一个动态转换为另一个动态的类型#_C#_Dynamic_Casting - Fatal编程技术网

C# 在c中,将一个动态转换为另一个动态的类型#

C# 在c中,将一个动态转换为另一个动态的类型#,c#,dynamic,casting,C#,Dynamic,Casting,我正试图编写一个通用函数,将反射的预期结果(但预期是由用户在配置中而不是在设计时提供的)与任意属性的实际结果进行比较 我遇到了一个问题,期望的类型在默认情况下并不总是反映返回的类型-例如,我的反射结果(在动态中)可能是int,其中期望的结果是enum成员(从int继承) 因此,我想做以下工作: if ((dCurrentValue as typeof(this.CheckValue)) != this.CheckValue) { oOut = false; } 然而,这似乎不起作用。通过在we

我正试图编写一个通用函数,将反射的预期结果(但预期是由用户在配置中而不是在设计时提供的)与任意属性的实际结果进行比较

我遇到了一个问题,期望的类型在默认情况下并不总是反映返回的类型-例如,我的反射结果(在动态中)可能是int,其中期望的结果是enum成员(从int继承)

因此,我想做以下工作:

if ((dCurrentValue as typeof(this.CheckValue)) != this.CheckValue) { oOut = false; }
然而,这似乎不起作用。通过在web上摸索,我发现System.Activator或Convert.ChangeType()可能是我的朋友。然而,到目前为止,它们并没有像我预期的那样工作-例如:

dCurrentValue = Convert.ChangeType(dCurrentValue, this.CheckValue.GetType());
引发一个异常(对于提醒我该问题的对),该异常从“System.Int32”到“Microsoft.Office.Core.MsotRestate”的转换无效,我知道该异常是错误的,因为:

(int)Microsoft.Office.Core.MsoTriState.msoTrue == -1                                    // true
((Microsoft.Office.Core.MsoTriState)(-1)) == Microsoft.Office.Core.MsoTriState.msoTrue  // true
注意,虽然我可以放入一个垫片来解决MsoTriState(即检查this.CheckValue的类型,如果适用的话显式强制转换),但我更愿意以一种适用于未知枚举条目的方式来完成这项工作

编辑:由于下面的评论,我在对表单进行测试之前添加了一个测试:

if (((Type) this.CheckValue.GetType()).IsEnum)
{
    dCurrentValue = Enum.Parse(this.CheckValue.GetType(), dCurrentValue.ToString());
}

这解决了我眼前的问题。我猜这与
Convert.ChangeType()
(正如我所提到的,它似乎不喜欢将枚举转换为int)相结合将涵盖大多数情况。

公共语言运行时类型(
Boolean
SByte
Byte
)实现<代码>转换仅适用于实现此接口的类型。基本类型之间的С转换不是问题。不属于公共语言运行时类型,但它实现了
IConvertible
。这意味着您可以使用
convert.ChangeType
轻松地从
Enum
转换为基本类型,但您不能简单地向后转换,这两种类型之间没有桥梁。这就是您捕获到从“System.Int32”到“Microsoft.Office.Core.MsoTriState”的无效强制转换的原因。
IConvertible
包含方法(
GetTypeCode
),该方法有助于获取有关
Enum
的基本类型的信息。我写了一些代码来解决你的问题

解决方案
我不知道我是否遵循,但您是否尝试过
Enum.Parse(…)
?我实际上没有-我是否以任何方式首先测试CheckValue是否为Enum?理想情况下,我希望避免1001
try{}catch{}
语句(上面的示例!=比较是众多比较之一,但很好地说明了这个问题)。不过我会尝试使用它……您可以使用CheckValue.GetType().IsEnum来找到答案。@Tobrian并检查关于
Enum.IsDefined
IsEnum
Enum.Parse
的答案,看起来它们适用于Enum(这就是我要讨论的)。我仍然想知道如何以我上面提到的方式强制强制转换(以防非枚举出现),但现在这解决了手头的问题。作为答案提交,我会接受!
public static class Comparer
{
    public static IConvertible CastToConvertible<T>(T value)
    {
        if (value is IConvertible)
        {
            return (IConvertible)Convert.ChangeType(value, ((IConvertible)value).GetTypeCode());
        }
        // this type is not supported
        throw new ArgumentException("Unknown type: " + value.GetType());
    }

    public static bool Equals<T1, T2>(T1 first, T2 second)
    {
        try
        {
            IConvertible firstConveted = CastToConvertible(first);
            IConvertible secondConverted = CastToConvertible(second);
            // standard Equals cannot compare two different types,
            // so here the second value is
            // converted to the type of the first value
            var secondChangedType = (IConvertible)Convert.ChangeType(
                secondConverted, firstConveted.GetTypeCode());
            return firstConveted.Equals(secondChangedType);
        }
        catch (Exception)
        {   
            // an exception might be caught in two cases:
            // 1. One of the values cannot be converted
            // to IConvertible interface.
            // 2. The second value cannot be converted 
            // to the type of the first value.
            return false;
        }
    }
}
[TestClass]
public class ComparerTests
{
    public enum ByteEnum : byte
    {
        One = 1, Two = 2
    }

    public enum IntEnum
    {
        One = 1, Two = 2, MegaLarge = 100500
    }

    [TestMethod]
    public void EqualsTest()
    {
        Assert.IsTrue(Comparer.Equals(2, 2));
        Assert.IsFalse(Comparer.Equals(1,2));
        Assert.IsTrue(Comparer.Equals(1, IntEnum.One));
        Assert.IsFalse(Comparer.Equals(1, IntEnum.Two));
        Assert.IsTrue(Comparer.Equals(ByteEnum.One, IntEnum.One));
        Assert.IsFalse(Comparer.Equals(ByteEnum.One, IntEnum.Two));
        Assert.IsFalse(Comparer.Equals(ByteEnum.One, IntEnum.MegaLarge)); 
    }
}