我正在尝试收集C#中发生装箱的所有情况:
将值类型转换为System.Object类型:
struct S { }
object box = new S();
Run Code Online (Sandbox Code Playgroud)将值类型转换为System.ValueType类型:
struct S { }
System.ValueType box = new S();
Run Code Online (Sandbox Code Playgroud)将枚举类型的值转换为System.Enum类型:
enum E { A }
System.Enum box = E.A;
Run Code Online (Sandbox Code Playgroud)将值类型转换为接口引用:
interface I { }
struct S : I { }
I box = new S();
Run Code Online (Sandbox Code Playgroud)在C#字符串连接中使用值类型:
char c = F();
string s1 = "char value will box" + c;
Run Code Online (Sandbox Code Playgroud)
注意:char类型的常量在编译时连接在一起
注意:由于6.0版的C#编译器优化串联涉及bool,char,IntPtr, …
C#4.0动态使用有一些奇怪的行为:
using System;
class Program {
public void Baz() { Console.WriteLine("Baz1"); }
static void CallBaz(dynamic x) { x.Baz(); }
static void Main(string[] args) {
dynamic a = new Program();
dynamic b = new { Baz = new Action(() => Console.WriteLine("Baz2")) };
CallBaz(a); // ok
CallBaz(b); // ok
CallBaz(a); // Unhandled Exception:
// Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
// The name 'Baz' is bound to a method and cannot be used like a property
}
}
Run Code Online (Sandbox Code Playgroud)
我正在使用Visual Studio 2010 Release Candidate.
这是一个错误吗?如果是真的,它会在Release中修复吗?
在C#中可以将方差注释添加到类型参数,约束为值类型:
interface IFoo<in T> where T : struct
{
void Boo(T x);
}
Run Code Online (Sandbox Code Playgroud)
如果在这种情况下方差注释完全没有意义,为什么编译器允许这样做?
C#4.0协同和逆变支持的一些奇怪行为:
using System;
class Program {
static void Foo(object x) { }
static void Main() {
Action<string> action = _ => { };
// C# 3.5 supports static co- and contravariant method groups
// conversions to delegates types, so this is perfectly legal:
action += Foo;
// since C# 4.0 much better supports co- and contravariance
// for interfaces and delegates, this is should be legal too:
action += new Action<object>(Foo);
}
}
Run Code Online (Sandbox Code Playgroud)
这是结果 ArgumentException: Delegates must be of the …
关于C#语言设计的小问题:))
如果我有这样的界面:
interface IFoo {
int Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
可以使用C#3.0自动实现的属性显式实现此类接口:
sealed class Foo : IFoo {
int IFoo.Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
但如果我在界面中有一个事件:
interface IFoo {
event EventHandler Event;
}
Run Code Online (Sandbox Code Playgroud)
并尝试使用类似字段的事件显式实现它:
sealed class Foo : IFoo {
event EventHandler IFoo.Event;
}
Run Code Online (Sandbox Code Playgroud)
我将得到以下编译器错误:
error CS0071: An explicit interface implementation of an event must use event accessor syntax
我认为类似字段的事件是自动实现属性的某种二元论.
所以我的问题是:这种限制的设计原因是什么?
我对C#语言的一些设计选择感兴趣.有一个在C#规范中的一个规则,允许使用方法组作为表达is操作:
class Foo {
static void Main() { if (Main is Foo) Main(); }
}
Run Code Online (Sandbox Code Playgroud)
上述条件总是错误的,因为规范说:
7.10.10是运营商
• 如果E是方法组或空文字,如果E的类型是引用类型或可空类型且E的值为null,则结果为false.
我的问题:允许在CLR中使用没有运行时表示的C#语言元素的目的/要点/原因是什么,就像这样的"运行时"运算符中的方法组一样is?
我已经阅读了很多有关类型,高级类型等等的有趣内容.默认情况下,Haskell支持两种类型:
** ? *最新的GHC语言扩展ConstraintKinds增加了一种新的:
Constraint在阅读这个邮件列表后,很明显可能存在另一种类型,但GHC不支持它(但这种支持是在.NET中实现的):
#我已经了解了多态种类,我想我理解这个想法.Haskell也支持明确的kinded量化.
所以我的问题是:
subkinding意思?它在哪里实施/有用?kinds,就像kinds一个类型系统在上面types?(只是感兴趣)让我们看一下F#为简单函数生成的代码:
let map_add valueToAdd xs =
xs |> Seq.map (fun x -> x + valueToAdd)
Run Code Online (Sandbox Code Playgroud)
生成的lambda表达式代码(F#功能值的实例)如下所示:
[Serializable]
internal class map_add@3 : FSharpFunc<int, int> {
public int valueToAdd;
internal map_add@3(int valueToAdd) { this.valueToAdd = valueToAdd; }
public override int Invoke(int x) { return (x + this.valueToAdd); }
}
Run Code Online (Sandbox Code Playgroud)
看看几乎相同的C#代码:
using System.Collections.Generic;
using System.Linq;
static class Program {
static IEnumerable<int> SelectAdd(IEnumerable<int> source, int valueToAdd) {
return source.Select(x => x + valueToAdd);
}
}
Run Code Online (Sandbox Code Playgroud)
并为C#lambda表达式生成代码:
[CompilerGenerated]
private sealed class <>c__DisplayClass1 {
public int …Run Code Online (Sandbox Code Playgroud) F#允许通过打开Checked模块使用经过检查的算术,它重新定义标准运算符作为检查运算符,例如:
open Checked
let x = 1 + System.Int32.MaxValue // overflow
Run Code Online (Sandbox Code Playgroud)
将导致算术溢出异常.
但是如果我想在一些小范围内使用经检查的算术,如C#允许使用关键字checked:
int x = 1 + int.MaxValue; // ok
int y = checked { 1 + int.MaxValue }; // overflow
Run Code Online (Sandbox Code Playgroud)
如何通过打开Checked模块或尽可能缩小模块来控制操作员重新定义的范围?
我对CLR如何实现这样的调用感兴趣:
abstract class A {
public abstract void Foo<T, U, V>();
}
A a = ...
a.Foo<int, string, decimal>(); // <=== ?
Run Code Online (Sandbox Code Playgroud)
这个调用是否会导致某种类型的哈希映射查找类型参数令牌作为键和编译的泛型方法特化(一个用于所有引用类型,所有值类型的不同代码)作为值?