【问题标题】:Can I check if a variable can be cast to a specified type?我可以检查一个变量是否可以转换为指定的类型吗?
【发布时间】:2011-10-25 22:03:29
【问题描述】:

我正在尝试验证是否可以将传递的变量转换为特定类型。我尝试了以下方法,但无法编译,所以我认为我的做法是错误的(我是 C# 新手)

string myType = "System.Int32";
string myValue = "42";

bool canBeCast = false;

try
{
  // try to convert the value to it's intended type to see if it's valid.
  var result = (Type.GetType(typeString))dataValue;
  canBeCast = true;
}
catch
{
  canBeCast = false;
}

我基本上是在尝试避免类似的大量 switch 语句

  switch(myType){
    case "System.Int32":
      try
      {
        var convertedValue = Convert.ToInt32(myValue);
      }
      catch (Exception)
      {
        canBeConverted = false;
      }
      break;
    case "another type":
      ...
  }

编辑:

好的,基本上我有一个已知输入类型的 db 表,如下所示:

CREATE TABLE [dbo].[MetadataTypes] (
    [typeName]  VARCHAR (50)  NOT NULL,
    [dataType]  VARCHAR (50)  NOT NULL,
    [typeRegex] VARCHAR (255) NULL
);

其中可能有诸如

之类的数据
"StartTime","System.DateTime",null
"TicketId","System.String","$[Ff][0-9]{7}^"

我的函数的输入将是一个 KeyValuePair,类似于

myInput = new KeyValuePair<string,string>("StartTime","31/12/2010 12:00");

我需要检查 KeyValuePair 的值是否属于 MetaDataType 预期的正确数据类型。

编辑答案:

Leon 非常接近我最终想出的解决方案。

作为参考,我的函数现在看起来像这样:

public Boolean ValidateMetadata(KeyValuePair<string, string> dataItem)
{

  // Look for known metadata with name match
  MetadataType type = _repository.GetMetadataTypes().SingleOrDefault(t => t.typeName == dataItem.Key);
  if (type == null) { return false; }

  // Get the data type and try to match to the passed in data item.
  Boolean isCorrectType = false;
  string typeString = type.dataType;
  string dataValue = dataItem.Value;

  try
  {
    var cValue = Convert.ChangeType(dataValue, Type.GetType(typeString));
    isCorrectType = true;
  }
  catch
  {
    isCorrectType = false;
  }

  //TODO: Validate against possible regex here....            

  return isCorrectType;

}

【问题讨论】:

  • 您期望什么类型的数据?您需要处理哪些?
  • 这不是选角,而是转换
  • 好的,Int32 只是我可能尝试验证的类型的一个示例。它可以是 DateTime、Boolean、Decimal 等。
  • @Nick:如果你总是来自 string,你需要解析。您应该对您想要它是什么类型有所了解,这就是您使用您提到的每种类型的TryParse 方法的地方。
  • 唉,Convert.ChangeType(object, type) 仅适用于实现 IConvertible 的对象

标签: c# casting type-conversion


【解决方案1】:

使用“as”运算符尝试强制转换:

var myObject = something as String;

if (myObject != null)
{
  // successfully cast
}
else
{
  // cast failed
}

如果转换失败,不会抛出异常,但目标对象将为 Null。

编辑:

如果你知道你想要什么类型的结果,你可以使用这样的辅助方法:

public static Object TryConvertTo<T>(string input)
{
    Object result = null;
    try
    {
        result = Convert.ChangeType(input, typeof(T));
    }
    catch
    {
    }

    return result;
}

【讨论】:

  • 类似于is,您不能只将string 转换为int。即使解析成功,每次都会失败。
  • 您的编辑与我的解决方案非常接近 :) 我只需要获取要从其名称转换为的类型。
  • @yoyo "as" 运算符确实会尝试强制转换。 See here"is" operator 是不转换的那个。
  • as 运算符仅适用于引用或可为空的类型,因此该解决方案并未涵盖所有情况。
  • @Leon 他的意思是显式转换——as 只会尝试“转换”为兼容类型——它实际上不会convert将 int 转换为字符串(即使你把它装箱)——as 不会返回一个新的/转换的对象。 -- 它只是返回具有不同类型句柄的相同对象(如果不能强制转换,则返回 null)。
【解决方案2】:

查看此链接:http://msdn.microsoft.com/en-us/library/scekt9xw(v=vs.71).aspx

is 运算符用于检查对象的运行时类型是否与给定类型兼容。 is 运算符用于以下形式的表达式:

if (expression is type){
    // do magic trick
}

你可以用什么?

【讨论】:

  • is 运算符在这种情况下不起作用,因为 stringint 是完全不同的类型。
  • 如果你知道它是什么类型,为什么还要解析呢?
  • @321X,解析一个数字并不是要弄清楚它是什么类型,而是要知道你想要它是什么类型。跨度>
【解决方案3】:

试试这个

return myType.IsInstanceOfType(myObject);

【讨论】:

  • 这对我的目的来说是完美的。我正在编写一个 MVC 验证器,需要检查传递给我的验证器 IsValid 函数的值是否属于给定(可能为空)类型。
【解决方案4】:

我想这就是你要找的东西:

var myValue = "42";
int parsedValue;

if (Int32.TryParse(myValue, out parsedValue)) {
    // it worked, and parsedValue is equal to 42
}
else {
    // it did not work and parsedValue is unmodified
}

编辑:为了清楚起见,isas 运算符的使用方式如下...

is 运算符将返回一个boolean 值来指示被测试的对象是否指定的类型或实现指定的接口。这就像问编译器“我的变量是这种类型吗?”:

var someString = "test";
var result = someString is IComparable; // result will be true

as 运算符尝试执行转换,如果不能,则返回 null 引用。这就像告诉编译器“我想将此变量用作这种类型”:

var someString = "test";
var comparable = someString as IComparable; // comparable will be of type String

如果您尝试这样做:

var someString = "42";
// using Int32? because the type must be a reference type to be used with as operator
var someIntValue = someString as Int32?;

编译器会报错:

无法通过内置转换来转换类型。

【讨论】:

    【解决方案5】:

    我知道它已经很老了,但是对于以现代方式寻找答案的人来说,会留下回复。从 C#7 您可以使用带有模式匹配的新开关 (https://docs.microsoft.com/pl-pl/dotnet/csharp/pattern-matching)

            switch (myObject)
            {
                case PlayerObject playerObject:
                    //this is player object type and can use also playerObject because it's already casted
                    break;
                case EnemyObject enemyObject:
                    //same here but we have enemy object type
                    break;
                default:
                    break;
            }
    

    【讨论】:

      【解决方案6】:

      您是否尝试过TryParse,它有一个布尔返回值来指示转换是否成功

      【讨论】:

      • 所以你建议TryTryParse()
      【解决方案7】:

      你可以做int.TryParse()函数:

      int myInt;
      bool parsed = int.TryParse(myVariable, out myInt);
      
      if (parsed) {
          // Do something with myInt or other logic
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-29
        • 1970-01-01
        • 1970-01-01
        • 2016-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多