初次使用IE9我真的是想说谁这么没脑子 地址栏和标签栏放一起。但是其实IE9也可以如此清爽。这不是IE9的另外一个候选版本。因为只要简单设置就可以了
在这里分享几个小地方。
1. 鼠标移到地址栏和标签栏中间。会变成可以拉伸的样子。这个拖拖试试。不过这个标签栏还是跟地址栏在一起啊L
看了很多人讨论Dynamic。不禁自己也想挖掘下。下面把自己的体会分享给大家
使用了dynamic关键字创建的对象实际上是一个object. 使用.net 4.0以下的Reflector就可以看到.
使用dynamic关键字后编译器将会将这个对象后面的PropertyName翻译成相应Binder调用。因此语法检查器会忽略检查此对象是否包含PropertyName.
真正的跟DLR有关的是在System.Dynamic下的类型。
大家可以实验一个叫ExpandoObject的东西
private static void Main(string[] args) { dynamic expandoObject = new ExpandoObject(); expandoObject. PropertyA = "PropertyA"; expandoObject.PropertyB = 2010; Console.WriteLine(expandoObject.PropertyA); Console.WriteLine(expandoObject.PropertyB); }
这个时候用dynamic是不是有点动态语言的感觉了?所以说 dynamic不是DLR的实现,
但要用DLR在C#里最好的途径可能就是使用dynimic了。
请看如下代码:
原始代码
public class Program { static void Main(string[] args) { Method1(); Method2(); Method3(); Method4(); } private static void Method1() { dynamic d = new TestClass(); d.TestProperty = ""; } private static void Method2() { TestClass t = new TestClass(); dynamic d1 = t; dynamic d2 = t; d1.TestProperty = ""; d2.TestProperty = ""; } private static void Method3() { dynamic d = new TestClass(); for (int i = 0; i < 100; i++) { d.TestProperty = i.ToString(); } } private static void Method4() { for (int i = 0; i < 100; i++) { dynamic d = new TestClass(); d.TestProperty = i.ToString(); } } class TestClass { public string TestProperty { get; set; } }
而且是一个dynamic生成一个Site .装在对应的Container中。
下面我们来看Method1 反编译后
private static void Method1()
{
object d = new TestClass();
if (<Method1>o__SiteContainer0.<>p__Site1 == null)
{
<Method1>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, "TestProperty", typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
}
<Method1>o__SiteContainer0.<>p__Site1.Target(<Method1>o__SiteContainer0.<>p__Site1, d, "");
}
可以看出d其实是个Object了访问属性通过Site实现,而且这里的Site判空,意味着可以缓存。
Method2反编译后
private static void Method2()
{
TestClass t = new TestClass();
object d1 = t;
object d2 = t;
if (<Method2>o__SiteContainer2.<>p__Site3 == null)
{
<Method2>o__SiteContainer2.<>p__Site3 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, "TestProperty", typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
}
<Method2>o__SiteContainer2.<>p__Site3.Target(<Method2>o__SiteContainer2.<>p__Site3, d1, "");
if (<Method2>o__SiteContainer2.<>p__Site4 == null)
{
<Method2>o__SiteContainer2.<>p__Site4 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, "TestProperty", typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
}
<Method2>o__SiteContainer2.<>p__Site4.Target(<Method2>o__SiteContainer2.<>p__Site4, d2, "");
}
虽然 d1 d2 都指向了 同一个对象t.但这里还是创建了两个Site。可见出现了多少个dynamic就会创建多少个site.
再看Method3和Method4private static void Method3() { object d = new TestClass(); for (int i = 0; i < 100; i++) { if (<Method3>o__SiteContainer5.<>p__Site6 == null) { <Method3>o__SiteContainer5.<>p__Site6 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, "TestProperty", typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) })); } <Method3>o__SiteContainer5.<>p__Site6.Target(<Method3>o__SiteContainer5.<>p__Site6, d, i.ToString()); } } private static void Method4() { for (int i = 0; i < 100; i++) { object d = new TestClass(); if (<Method4>o__SiteContainer7.<>p__Site8 == null) { <Method4>o__SiteContainer7.<>p__Site8 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, "TestProperty", typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) })); } <Method4>o__SiteContainer7.<>p__Site8.Target(<Method4>o__SiteContainer7.<>p__Site8, d, i.ToString()); } }
可见dynamic写在循环里和循环外都是一样的。因为编译器只看到一个dynamic。只生成了一个site.由于site一样且经过缓存,
可以猜想性能不会相差太。
由于Site和SiteContainer都是Staic的,所以凡是重复对一个dynamic操作多次都会受益于这种cache。眼看要下班了。笔先收一下,有时间再写:-)
发现IE9 羞辱 Chorme9的一个地方
http://ie.microsoft.com/testdrive/Default.html
IE的这个Banner针对浏览器选择显示什么图片
用Chorme打开 会变成这个
正常情况下运行Speed Reading Chorme完成的很不错。
按照他的提示 about:flags 中打开
现在看看Chrome
经过验证发现此问题只出现在9.0.587.0.dev
之前版本开启GPU Accelerated Canvas 2D后Chrome的渲染速度令人惊讶。Fps稳定在60最大值。
怀疑IE9的开发组天天都在测试Chrome啊~
另外 如果使用Opera打开这个网页的话 Banner会变成:-)
微软,邪恶无所不在~