是否有更现代的,可能是面向对象的,相当于Jack Crenshaw的" Let's Build a Compiler "系列?
不久前,我偶然发现了" 让我们编写一个编译器 ",并且无法拒绝编写一些代码.我在C#中编写了一个递归下降的C编译器,输出.NET CIL."写一次,到处泄漏"是我的口号.
太糟糕了,直到太晚才发现解析C是一场噩梦.
我现在有兴趣用Java编写一个Java编译器,它输出.NET CIL或程序集,目的是自引导.我希望可能会有更新的教程.
另外,您是否会花更多时间进行前期设计,或者只是编写大量测试来支持无情重构的能力.回想起来,我倾向于后者.编译器工作但代码非常糟糕.
可能重复:
为什么.net/C#不会消除尾递归?
请使用以下C#代码:
using System;
namespace TailTest
{
class MainClass
{
public static void Main (string[] args)
{
Counter(0);
}
static void Counter(int i)
{
Console.WriteLine(i);
if (i < int.MaxValue) Counter(++i);
}
}
}
Run Code Online (Sandbox Code Playgroud)
C#编译器(无论如何)我会将Counter方法编译成以下CIL:
.method private static hidebysig default void Counter (int32 i) cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call void class [mscorlib]System.Console::WriteLine(int32)
IL_0006: ldarg.0
IL_0007: ldc.i4 2147483647
IL_000c: bge IL_0019
IL_0011: ldarg.0
IL_0012: ldc.i4.1
IL_0013: add
IL_0014: call void class TailTest.MainClass::Counter(int32)
IL_0019: ret
}
Run Code Online (Sandbox Code Playgroud)
上面代码的问题是它会导致堆栈溢出(在我的硬件上约为i = …
这是我现在有一段时间的问题:
什么时候公开公开这个领域是有意义的?
public class SomeClass()
{
public int backing;
}
Run Code Online (Sandbox Code Playgroud)
这样做的缺点(除了激怒OOP精英)之外,如果您需要在此数据之上添加任何逻辑,则必须对API进行重大更改.我想这就是精英主义者所关注的.
Java和C#的最佳实践一直是使用getter/setter或属性来访问字段.
public class SomeClass()
{
private int backing;
public int getBacking()
{
return backing;
}
public void setBacking(int v)
{
backing = v;
}
}
Run Code Online (Sandbox Code Playgroud)
C#已将其演变为具有自动属性的非常简单的语法:
public class SomeClass()
{
public int Backing { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
懒惰我仍觉得这太长了,因为它发现自己做了很多事情.更重要的是,我不确定我知道公共领域会更有意义.
为什么不直接将公开声明的字段视为幕后的属性(或方法)?这样就不可能激怒去耦神灵,并且不需要打字.
public class SomeClass()
{
public int backing; // The same as public int backing { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
对于除了包装底层字段之外什么都不做的属性,我很确定JIT优化了方法调用,因此性能可能不是问题.有什么想法吗?(除了字段名称的正确案例约定外)
编辑:感谢所有的回复.我觉得也许不是每个人都理解我的问题.什么时候公共场地比房产更好?为什么这是一个更好的选择?如果唯一的原因是方便(减少键入和混乱),那么只要遇到公共字段,编译器就会在"引擎盖下"生成属性会有什么缺点.基本上,创建一个真正的公共领域是不可能的(因为它们都是属性).这会有什么问题?谢谢.
我刚刚开始意识到得墨忒耳法则.
像很多事情一样,我意识到这是我已经在做的事情,但没有名字.虽然有几个地方我似乎违反了它.
例如...
我可能有一个Address对象:
public class Address : IAddress
{
public string StreetAddress { get; set; }
public string City { get; set; }
public int Zip { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
和一个Customer对象:
public class Customer : ICustomer
{
private IAddress address;
Customer()
{
Address = null;
}
public string Name { get; set; }
public IAddress
{
get
{
if (address == null)
{
address = new Address();
}
return address;
}
set
{
address = value; …Run Code Online (Sandbox Code Playgroud) 几天前我在"C#匿名递归"中浏览了这个网站.本文的主旨是以下代码在C#中不起作用:
Func<int, int> fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;
Run Code Online (Sandbox Code Playgroud)
然后,文章详细介绍了如何使用currying和Y-combinator回到C#中的"Anonymous Recursion".这很有趣,但我担心日常编码有点复杂.此时至少......
我喜欢看自己的东西,所以我打开了Mono CSharp REPL并输入了该行.没有错误.所以,我进来了fib(8);.令我非常惊讶的是,它奏效了!REPL回复了21!
我想也许这可能是REPL的一些魔力,所以我点了'vi',输入以下程序,然后编译它.
using System;
public class Program
{
public static void Main(string[] args)
{
int x = int.Parse(args[0]);
Func<int, int> fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;
Console.WriteLine(fib(x));
}
}
Run Code Online (Sandbox Code Playgroud)
它也完美地建造和运行!
我在Mac上运行Mono 2.10.我现在无法访问Windows计算机,所以我无法在Windows上的.NET上进行测试.
这是在.NET上修复过的还是Mono的静音功能?这篇文章已经有几年了.
如果它只是单声道,我不能等待下一次面试,他们要求我用我选择的语言(Mono …
这不是一个特别的C#问题,但它的C#版本switch让我问这个问题.
为什么我必须明确声明我不想从一个case陈述到下一个陈述而不是指示何时我想要通过?
在C#中,编译器不会让你从一个case语句落到下一个语句(除非case语句为空),但它强制你break在每个语句的末尾放置一个显式.switch我写的绝大多数陈述都没有落空.
int x = 4;
string result;
switch (x)
{
case 1:
result = "One";
break;
case 2:
result = "A couple";
break;
case 3:
case 4:
result = "Three or four";
break;
/*
case 5:
result = "Five"; // Here be an error! A common typo for me!!!
*/
default:
result = "Five or more";
break;
}
Run Code Online (Sandbox Code Playgroud)
上面的例子是为了表明可能性.实际落入的次数(如上面的3到4之间)是最小的.如果我从上面的案例5中删除了注释,C#编译器会将其作为错误捕获.如果编译器完全知道我想要做什么,为什么我必须手动修复它?
以下不会更好吗?
int x = 4;
string result; …Run Code Online (Sandbox Code Playgroud) 我正在编写一个我在Mac OS X上运行的ASP.NET MVC3应用程序.它运行良好,但我有一个未解决的问题.我正在使用Razor语法.例如,这是登录页面的简化版本:
@model Livestream.LoginModel
<!DOCTYPE html>
<html>
<head>
<title>Remote Observation</title>
<link type="text/css" rel="stylesheet" media="all" href="/Content/CSS/main.css" />
</head>
<body>
@{
dynamic dave = "Sign In";
}
<div class='normal center'>
<p><img src='/Content/images/logo.png' /></p>
@using(Html.BeginForm("Login", "Main")) {
<div class='loginBox'>
<p>Username<br />@Html.TextBoxFor(m => m.Username)</p>
<p>Password<br />@Html.PasswordFor(m => m.Password)</p>
<p><input type='submit' value='@dave'></p>
</div>
}
</div>
<script>
document.getElementById('Username').focus();
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
好的,所以没问题.它在Mac OS X和Linux上都很好用.
阅读评论后,这个职位由斯科特谷,我想我明白,我可以代替@model Livestream.LoginModel使用@model dynamic.当我尝试它时,它无法在OS X或Linux上运行.
鉴于我在ASP.NET中开发,它可能看起来很疯狂但我无法访问带有.NET的Windows机器来尝试这一点.我明显使用Mono.
我应该能够使用@model dynamic或者是否在那篇文章中误解了斯科特?还有什么我需要做的才能让它发挥作用吗?或者这是Mono中的一个错误?
我的应用程序使用的是.NET 4配置文件(CLR 4.0),因此它并不支持动态.我可以在代码中的其他位置使用动态. …
c# ×5
mono ×3
oop ×3
.net ×2
java ×2
refactoring ×2
asp.net-mvc ×1
defaults ×1
fall-through ×1
object ×1
razor ×1
recursion ×1
y-combinator ×1