1

在我的代码中,我在 global.asax 中注册了路由,如下所示:

void RegisterRoutes(RouteCollection routes)
{
   routes.MapPageRoute(
    "product",
    "product/{id}",
    "~/index.aspx"
);

然后在我的 index.aspx 页面中,我想测试 {id} 值是否为整数:

if (Page.RouteData.Values["id"] as int? != null)   
//always evaluate as null even id is an integer in the URL, ex: /product/1

我知道我可以使用其他一些方法(例如 int.TryParse 或this)来实现相同的目标,但是在这种情况下使用“as”是否有意义?

4

5 回答 5

5

The way to go depends on what is really stored in Values["id"]. If it is in fact an int, you can test for int with Values["id"] is int. The Values[] property is typed as object. Therefore it can be null. But this does NOT mean, that the stored int is a Nullable<int>. (see my update below.)

If you assign an int (and all other non-reference types) to an object variable or property, it will be boxed. I.e. it will be packed into an object of the corresponding type. int or System.Int32 exists as value type as well as a boxed and immutable System.Int32 reference type. Because of its immutability, you don't notice that it is a reference type. An int can be boxed with object obj = 5; and unboxed with int i = (int)obj;.

On the other hand, if the id was stored as string then you would have to convert it to a number

int id;
if (Int32.TryParse((string)Page.RouteData.Values["id"], out id)) {
    // use id here
}

UPDATE:

There seems to be some confusion with null and Nullable<T>.

int? i; // Same as Nullable<int> or Nullable<System.Int32> or System.Int32?
object obj;
bool test;

i = null;
test = i.HasValue; // ==> false
test = i == null;  // ==> true

// Now comes the strange part

obj = 5;           // The int is boxed here.
// Debugger shows type of obj as "object {int}"
test = obj is int;   // ==> true
test = obj is int?;   // ==> true
int x = (int)obj;  // ==> 5, the int is unboxed here.

// But

obj = null;
// Debugger shows type of obj as "object"
test = obj is int; // ==> false
test = obj is int?; // ==> false
test = obj == null; // ==> true

// And
i = 5;
obj = i; // i is a Nullable<int>
// Debugger shows type of obj as "object {int}"
test = obj is int; // ==> true
test = obj is int?; // ==> true
test = obj == null; // ==> false

i = null;
obj = i;
// Debugger shows type of obj as "object"
test = obj is int; // ==> false
test = obj is int?; // ==> false
test = obj == null; // ==> true

Both obj is int and obj is int? return true if obj contains an int number but both return false if obj contains null! A null Nullable<int> is converted to (object)null when asssigned to obj and is no more Nullable<int>.

The debugger shows the type of obj as object {int} when there is a number stored, no matter whether an int or an int? was assigned! The type of obj is object when null is stored.

So Chuong Le is in fact right!

于 2012-10-03T15:07:20.430 回答
3

我建议您使用Int.TryParse,因为该值很可能是一个字符串。不要使用,Int.Parse因为您还必须处理异常,并且您通常希望避免编写可能引发异常的代码(即使您正在处理它们)。

usingas并不是一个很好的解决方案,因为它迫使您使用 nullable int;如果你走这is条路线,那么当传入的值是一种类型时,几乎可以保证它不起作用。string

关于is辩论,我在 VS 中运行了这个:

string value = "42";
object answerToUniverse = value;
if (answerToUniverse is int)
{
    Console.WriteLine("It's an integer!");
}
else
{
    Console.WriteLine("It's NOT an integer!");
}

结果是:它不是整数!

于 2012-10-03T15:00:21.787 回答
0

也许你真的想这样做,

var idString = Page.RouteData.Values["id"] as string;
int id;
if (int.TryParse(idString, out id))
{
   // id is now a valid number 
}
else
{
   // your types are confused
}
于 2012-10-03T15:00:59.903 回答
0

看起来您想要检查而不是类型,这意味着您并不真正关心类型是什么。

在这种情况下,这是我可以推荐的最佳方法:

object idValue = Page.RouteData.Values["id"];
int dummy;
if (idValue != null && Int32.TryParse(idValue.ToString(), out dummy))
{
    //value is integer!
}

这样,类型是什么都没有关系。如果它是整数、双精度、字符串甚至是具有适当ToString()覆盖的复杂类型,它将起作用。

于 2012-10-03T15:01:27.580 回答
0

as is a safe cast. It will try and cast the provided value to the desired type, returning null instead of throwing an exception when a standard cast would.

Therefore unless Page.RouteData.Values["id"] was an integer object this would not work and you need to user the alternative methods you suggested.

One was could be to use an extension method

public static class IntExtensions {
   public static int? AsInt(this string source) {
     int result;
     return (int.TryParse(source,out result)) ? (int?)null : result;
   }

   public static bool IsInt(this string source) {
     return source.AsInt.HasValue;
   }
}

Allowing you to do

if (Page.RouteData.Values["id"].IsInt())
于 2012-10-03T15:02:08.637 回答