4

如链接所示:http: //msdn.microsoft.com/en-us/library/bb383973.aspx

...隐式类型的局部变量是强类型的,就像您自己声明了类型一样,但是编译器确定类型...

但我有这样一段代码:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (Session["user"] == null) Response.Redirect("Default.aspx");

        StringBuilder sb = new StringBuilder();

        foreach (var item in Session)
        {
            sb.Append("Session Parameter: [");
            sb.Append(item);
            sb.Append("]<p />Guid Value: [");
            sb.Append(Session[item] + "]");
        }

        Response.Write(sb.ToString());
    }

我在 Visual Studio 中遇到这样的错误:

参数 1:无法从 'object' 转换为 'string' 的行:

 sb.Append(Session[item] + "]");

但是item在运行时将其识别string为我在调试器中查看的类型。

当我var在 msdn/in 上阅读书籍时,我认为这var与 RTTI 无关。编译器只是在编译时使用这种隐式类型在显式类型等上更改变量string, int

为什么我会发现这样的错误?

4

7 回答 7

8

C# 中的var声明是强类型的,但在这种情况下,您正在处理 value 中的非泛型集合类型Session。这会导致 C# 选择object的类型,item因此您在尝试item在需要string.

对于非泛型集合,您仍需要在foreach块中显式键入迭代器变量

foreach(string item in Session) { 
  ...
}
于 2013-03-09T02:00:03.207 回答
3

“为什么我会发现这样的错误?” - 因为sb.Append(Session[item] + "]");期待一个字符串 - 所以你需要将它Session[item]转换为一个字符串:

sb.Append(((string)Session[item]) + "]");

根据 MSDN 文章How to: Read Values from Session State

于 2013-03-09T02:00:08.157 回答
2

在这种情况下,Session是一个HttpSessionState实现IEnumerable(尽管如果它实现也会发生同样的情况IEnumerable<object>),所以你var被编译器映射到:

  foreach (object item in Session)
  {

在这种情况下,这很可能是IEnumerable,因此您需要在 中明确指定类型foreach

  foreach (string item in Session)
  {

foreach对于非泛型IEnumerable集合,这是允许的。

至于你的主要问题:

C# var 有强类型吗?

是的。在这种情况下,集合本身不提供强类型,因此var使用System.Object.

于 2013-03-09T01:59:55.310 回答
1

你是对的,var是静态输入的(即在编译时)。然而,的静态类型var来自上下文,它允许编译器派生var.

Sessionwhich implements的情况下IEnumerable,编译器可以派生的唯一类型是object,导致您描述的错误。

已经Session实现了,比如说,IEnumerable<string>循环var中的 将等效于string,而不是object

于 2013-03-09T02:00:22.443 回答
1

在您的示例中,它归结为集合Session的类型。在这种情况下,它是对象的集合,因此编译器var item会将object item.

于 2013-03-09T02:00:44.637 回答
1

正如其他答案所表明的那样,Session 的 Item 属性(这是默认索引器)是 object 类型的。这就是您从索引器获取对象的原因 - 这是它的返回类型。

http://msdn.microsoft.com/en-us/library/k8s0kehy(v=vs.100).aspx

于 2013-03-09T02:01:10.627 回答
1

这是因为对象是不同的类型。很像为什么派生类与其基类不同(例如:)class D : B{}。所有类类型都继承Object,值(结构)我相信没有。他们需要装在盒子里。该Session系列只是说它有一堆物品,里面可能有任何东西。除非您要求(通过 typecast 或 is 关键字),否则运行时不会尝试检查。(更多关于下面的编译器)

The var in that foreach is saying this variable (item) should be whatever type Session enumerator returns. For the most part specifying a different type there is like a typecast.

Just because something is a class or boxes (which means it is an object) doesn't mean the compiler has any idea of what the object actually is. In fact I think the standards suggest if something becomes an object the compiler should not auto convert it even if it knows what type it actually is (perhaps it knows from a few lines above)

于 2013-03-09T02:03:45.073 回答