BCL中的许多方法都标有 [MethodImpl(MethodImplOptions.InternalCall)]属性.这表明 "方法是在公共语言运行时本身内实现的".
以这种方式设计框架的重点是指定了运行时将被强制实现的显式CIL指令?最终,该属性正在为运行时创建合同义务,但在某种程度上,我觉得这种方式令人困惑,而且不是很明显.
例如,Math.Pow本来可以用这种方式编写(请原谅我非正式的C#+ IL和IL本身,如果它不好的话;这只是一个解释我的观点的样本):
public static double Pow(double x, double y)
{
ldarg.0
ldarg.1
pow // Dedicated CIL instruction
ret
}
Run Code Online (Sandbox Code Playgroud)
而不是当前的方式:
[MethodImpl(MethodImplOptions.InternalCall)]
public static double Pow(double x, double y);
Run Code Online (Sandbox Code Playgroud)
为什么MethodImplOptions.InternalCall存在?
我经常听说在.NET 2.0内存模型中,写入始终使用释放围栏.这是真的?这是否意味着即使没有明确的内存屏障或锁定,也不可能在不同于创建它的线程上观察部分构造的对象(仅考虑引用类型)?我显然排除了构造函数泄漏this引用的情况.
例如,假设我们有不可变的引用类型:
public class Person
{
public string Name { get; private set; }
public int Age { get; private set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
Run Code Online (Sandbox Code Playgroud)
是否可以使用以下代码观察除"John 20"和"Jack 21"之外的任何输出,例如"null 20"或"Jack 0"?
// We could make this volatile to freshen the read, but I don't want
// to complicate the core of the question.
private Person person;
private void Thread1()
{
while (true)
{
var personCopy = person; …Run Code Online (Sandbox Code Playgroud) 为什么不能在C#中的对象初始值设定项中分配事件和属性?这样做似乎很自然.
var myObject = new MyClass()
{
Property = value,
Event1 = actor,
// or
Event2 += actor
};
Run Code Online (Sandbox Code Playgroud)
还是有一些我不知道的技巧?
委托有两种描述:第一种是在第三方程序集中:
public delegate void ClickMenuItem (object sender, EventArgs e)
Run Code Online (Sandbox Code Playgroud)
二,标准:
public delegate void EventHandler (object sender, EventArgs e);
Run Code Online (Sandbox Code Playgroud)
我正在尝试编写一个接收EventHandler类型参数的方法,并使用参数ClickMenuItem调用第三方库.
如何将ClickMenuItem转换为EventHandler?
我很高兴C#不允许你访问静态成员,就像'他们是实例成员一样.这避免了Java中的常见错误:
Thread t = new Thread(..);
t.sleep(..); //Probably doesn't do what the programmer intended.
Run Code Online (Sandbox Code Playgroud)
在另一方面,它不会让你访问"到"派生类型的静态成员.除了运算符(它可以让你免于编写演员表),我无法想到任何实际上有用的情况.事实上,它积极鼓励错误,例如:
// Nasty surprises ahead - won't throw; does something unintended:
// Creates a HttpWebRequest instead.
var ftpRequest = FtpWebRequest.Create(@"http://www.stackoverflow.com");
// Something seriously wrong here.
var areRefEqual = Dictionary<string, int>.ReferenceEquals(dict1, dict2);
Run Code Online (Sandbox Code Playgroud)
我个人保持了承诺,当我通过陌生的API搜索我的方式过类似的错误(我记得开始了与表达式目录树,我打BinaryExpression.在编辑器中,并想知道为什么地球上的智能感知人给我MakeUnary作为一个选项).
在我的(短视)意见中,此功能:
(国际海事组织,运营商是一个特殊情况,值得他们自己讨论.)
鉴于C#通常是"成功的一块"语言,为什么这个功能存在?我看不到它的好处(除了'可发现',它总是可以在IDE中解决),但我看到很多问题.
我编写了一个DSL和一个从中生成.NET表达式树的编译器.树中的所有表达式都是无副作用的,并且表达式保证是"非语句"表达式(没有本地,循环,块等).(编辑:树可能包括文字,属性访问,标准操作符和函数调用 - 这可能正在做一些奇特的事情,如内部的memoization,但外部副作用是免费的).
现在我想对它执行"Common sub-expression elimination"优化.
例如,给定一个对应于C#lambda的树:
foo => (foo.Bar * 5 + foo.Baz * 2 > 7)
|| (foo.Bar * 5 + foo.Baz * 2 < 3)
|| (foo.Bar * 5 + 3 == foo.Xyz)
Run Code Online (Sandbox Code Playgroud)
...我想生成树等价的(忽略一些短路语义被忽略的事实):
foo =>
{
var local1 = foo.Bar * 5;
// Notice that this local depends on the first one.
var local2 = local1 + foo.Baz * 2;
// Notice that no unnecessary locals have been generated.
return local2 > 7 || …Run Code Online (Sandbox Code Playgroud) 所以我最近一直在玩动态构建表达式树,并遇到了这种方法,这看起来有点奇怪.起初,在经常编写代码之后,我认为"哦,这正是我需要的"
var left = member is FieldInfo ? Expression.Field(instance, (FieldInfo)member) : Expression.Property(instance, (PropertyInfo)member);
var right = ...
var assign = Expression.Assign(left, right);
Run Code Online (Sandbox Code Playgroud)
是的,我知道有Expression.PropertyOrField()呼叫,但它确实往返于反射,以便按名称查找成员,我通常已经拥有MemberInfo实例.
所以无论如何,我认为Expression.Bind()对我有用,但它做了一些我不太懂的事情.给出以下代码:
void Main()
{
var m = typeof(Foo).GetField("Bar");
Expression.Bind(m, Expression.Constant("")).Dump();
}
public class Foo
{
public string Bar;
}
Run Code Online (Sandbox Code Playgroud)
它产生MemberAssignment表达Bar = "".但是没有实例也没有静态引用.我如何将这个表达式应用于和实例Foo?我找不到任何使用此方法的示例.
Dictionary<TKey, TValue>在.NET中是否有任何关于命名关联数组(例如)的约定/指南?
例如,有更好的方法来命名dict:
var dict = new Dictionary<Foo, Bar>();
Run Code Online (Sandbox Code Playgroud)
我用过/看过的一些名字:
foosToBars
mapFromFooToBar
barsByFoo
barsForFoos
Run Code Online (Sandbox Code Playgroud)
我还看到BCL中的某些类型选择"更好"的发音名称,这些名称并不直接揭示键和值应该表示的内容,例如在此方法中.
多图(例如ILookup<TKey, TElement>)如何?
编辑:
也许我的例子稍差; 我并不是要专注于键和值的类型.
如果它是这样的:
// key = Name of person, value = Age of person
var dict = new Dictionary<string, int>();
Run Code Online (Sandbox Code Playgroud)
样本更新为:
namesToAges
mapFromNameToAge
agesByName
agesForNames
Run Code Online (Sandbox Code Playgroud) 考虑这个课程:
/// <summary>
/// Dummy implementation of a parser for the purpose of the test
/// </summary>
class Parser
{
public List<T> ReadList<T>(Func<T> readFunctor)
{
return Enumerable.Range(0, 10).Select(i => readFunctor()).ToList();
}
public int ReadInt32()
{
return 12;
}
public string ReadString()
{
return "string";
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用已编译的lambda表达式树生成以下调用:
Parser parser = new Parser();
List<int> list = parser.ReadList(parser.ReadInt32);
Run Code Online (Sandbox Code Playgroud)
但是,表现并不完全相同......
class Program
{
private const int MAX = 1000000;
static void Main(string[] args)
{
DirectCall();
LambdaCall();
CompiledLambdaCall();
}
static void DirectCall()
{
Parser …Run Code Online (Sandbox Code Playgroud) 我创建了一个表达式,我正在使用它进行排序工作正常,直到我遇到一个DateTime字段,我得到以下错误(在第二行):
'System.DateTime'类型的表达式不能用于返回类型'System.Object'
这是我的代码:
ParameterExpression param = Expression.Parameter(typeof(MyEntity), "x");
Expression<Func<MyEntity, object>> sortExpression =
Expression.Lambda<Func<AMyEntity, object>>(
Expression.Property(param, sortKey), param);
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮忙吗?
c# ×9
.net ×6
delegates ×2
expression ×2
linq ×2
algorithm ×1
cil ×1
clr ×1
coding-style ×1
dictionary ×1
events ×1
inheritance ×1
lambda ×1
memory-model ×1
optimization ×1
reflection ×1
static ×1