6

回到基础...

对于引用类型,可以这样做:

        SomeType someObject = firstObject as SomeType;
        if (someObject == null)
        {
            // Handle the situation gracefully
        }
        else
        {
            // Do stuff
        }

对于值类型,我的理解是我们有隐式转换(没有数据丢失)、显式转换(如果有数据丢失的风险则需要)、Convert类(我认为是“转换包装器”)以及特定于类型的转换(例如double x = Double.Parse("2");),但我没有找到与as上面的运算符类似的任何东西。

所以,我的问题是:该框架是否提供了一些方法/操作员/技术来执行以下操作:

        if (!Convert.CanConvert(someValue, someValueType))
        {
            // Beware! Data loss can occur
        }
        else
        {
            // No data loss here
        }

如果没有,那里的任何人都可以提出一种可靠的方法来构建一种这样的CanConvert方法吗?

非常感谢!

编辑(1):用户案例/问题如下:给定代码的消费者(我的另一个自我,但这无关紧要)传递的东西,(1)检查某物是否是一个数字(很容易)和(2)将某些内容放在适合的“最小”数字类型中,而不会导致数据丢失。

一些背景:我正在尝试做的事情的本质是数学而不是技术:我正在尝试查看是否/如何将现有的数字类型适合某种形式的代数层次结构 Monoid=>Group=> Ring=>Field(或其简化版本)。在处理这个问题时,不太确定如何,“一件事导致另一件事”,我发现自己不得不处理类型转换......

4

6 回答 6

3

各种值类型的 TryParse 方法怎么样?

int x;

if (int.TryParse(someType.ToString(), out x))
    return x;
于 2010-01-23T18:30:56.347 回答
2

亨克非常有钱。如果我愿意,我想在他的回答中添加一些内容:

.NET Framework 中的值类型转换使用IConvertible接口进行。该类Convert的几乎所有方法都使用了它。这与 C# 中的隐式/显式转换运算符非常不同,后者只是另一种形式的语法糖。

如果你这样写:

public struct Duck
{
    public static implicit operator Goose(Duck d)
    {
        ...
    }
}

.NET Framework 本身并不知道这存在。它以 an 形式发出,op_implicit由编译语言决定如何使用它。并非每种 MSIL 语言都支持这些。所以这段代码有效:

Goose g1 = duck;

此代码不会:

Goose g1 = (Goose)Convert.ChangeType(duck, typeof(Goose));

为了实现一个CanConvert知道隐式/显式转换运算符的方法,您实际上必须使用反射来检查各个op_方法,我不得不建议不要这样做 - 我在实践中看不到它的用处.

于 2010-01-23T18:56:28.743 回答
1

运算符是基于继承的as,值类型不继承。您可能可以编写 aCanConvert()但它必须与 Boxed 值类型一起使用,并且您通常希望避免装箱。

所以,可能:是,理想:否。

也许您可以添加一个您想要使用它的用例场景,然后我们可以推荐替代方案。

回复:编辑(1)

我希望您知道,数值类型系统主要是历史包袱,并不遵循非常合乎逻辑的规则。例如,没有short计算之类的东西,它们总是在做任何事情之前转换为 int 。

但也许你可以用环和场来定义这种行为,代数对我来说已经“过了很长时间”。

于 2010-01-23T18:32:59.877 回答
1

看看Convert.ChangeType。您可以劫持它以满足您的目的,尽管由于异常抛出和重复转换会很慢。

于 2010-01-23T18:36:15.280 回答
1

“as”关键字基本上是一个安全的向下转换。由于所有值类型都是密封的,因此它们不能被继承。

所以你的代码是:

if (firstObject is MyValueType)
{
   MyValueType obj = (MyValueType) firstObject;
}
else
{
}
于 2010-01-23T18:40:09.297 回答
1

我认为您误解了 as 运营商的观点。as 运算符大致等价于以下代码:

if (firstObject is SomeType)
  return (SomeType)firstObject;
else
  return null;

更多的是继承检查。(如List实现IList)

值类型不支持继承,这是有充分理由的。Double 和 Int64 都以完全不同的方式存储数字 1。

基本上,您想要的是一种方法,可以为您确定数字转换是否无损。那么我反驳“为什么?”。虽然 CLR 支持的格式很多,但转换规则通常非常简单。例如 Int32 -> Double 是无损的,任何从“更小”到“更大”的转换都是无损的,例如 SByte -> Int64。

另一个问题是,你的例子中的 false 意味着什么?我想说的很少,例如:

Convert.CanConvert(123456789.12345F, typeof(Byte))

错误的结果有什么用?您暗示这是针对 Int32 -> Single 之类的情况,其中一些数据会丢失,但在这种情况下会丢失大量数据,因为“最接近”的字节表示是 255。

正是因为这两个问题,才没有这样的方法。

于 2010-01-23T18:49:55.007 回答