The C# Design Process

C#首席架构师安德斯·赫尔伯格讨论了C#的设计流程及可用性研究与审美在语言设计中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The C# Design Process
A Conversation with Anders Hejlsberg, Part I
by Bill Venners with Bruce Eckel
August 4, 2003

Summary
Anders Hejlsberg, the lead C# architect, talks with Bruce Eckel and Bill Venners about the process used by the team that designed C#, and the relative merits of usability studies and good taste in language design.
Anders Hejlsberg, a distinguished engineer at Microsoft, led the team that designed the C# (pronounced C Sharp) programming language. Hejlsberg first vaulted onto the software world stage in the early eighties by creating a Pascal compiler for MS-DOS and CP/M. A very young company called Borland soon hired Hejlsberg and bought his compiler, which was thereafter marketed as Turbo Pascal. At Borland, Hejlsberg continued to develop Turbo Pascal and eventually led the team that designed Turbo Pascal's replacement: Delphi. In 1996, after 13 years with Borland, Hejlsberg joined Microsoft, where he initially worked as an architect of Visual J++ and the Windows Foundation Classes (WFC). Subsequently, Hejlsberg was chief designer of C# and a key participant in the creation of the .NET framework. Currently, Anders Hejlsberg leads the continued development of the C# programming language.

On July 30, 2003, Bruce Eckel, author of Thinking in C++ and Thinking in Java, and Bill Venners, editor-in-chief of Artima.com, met with Anders Hejlsberg in his office at Microsoft in Redmond, Washington. In this interview, which will be published in multiple installments on Artima.com and on an audio CD-ROM to be released this fall by Bruce Eckel, Anders Hejlsberg discusses many design choices of the C# language and the .NET framework. In this initial installment, Hejlsberg discusses the process used by the team that designed C#, and the relative merits of usability studies and good taste in language design.

Designing with a Living Agenda
Bruce Eckel: I've heard C# was created in a room with a group of designers.

Anders Hejlsberg: Yes. It was the same room for four years. We're still in that room every Monday, Wednesday, and Friday.

Bruce Eckel: I'm curious about the design process for C#. I've been involved in several different language designs, either directly or peripherally. In the Python process, for example, Guido van Rossum is humorously referred to as the benevolent dictator.

Anders Hejlsberg: That's sort of my same position.

Bruce Eckel: You are the benevolent dictator for C#?

Anders Hejlsberg: I'm the tie breaker. Once we've gone around an issue enough, and it is time to just make a decision one way or the other, I make it. But in most cases the decision is obvious.

Bruce Eckel: Is that similar to how Turbo Pascal and Delphi were designed?

Anders Hejlsberg: Those were less formal. I designed Turbo Pascal mostly by myself. I designed Delphi with Chuck Jazdzewski and Gary Whizin, but the group was small enough that we didn't really need a formal process. For C#, on the other hand, it has worked really well to formalize: every Monday, Wednesday, and Friday from 1:00 to 3:00, we have a regularly scheduled meeting. We have a living agenda. Issues bubble to the top, and we knock them off. We have a wiki now on the internal web with the issues list, resolutions for them, and so on.

Bruce Eckel: How do issues bubble to the top?

Anders Hejlsberg: Well, they just sort of do. We have many ways customers can give input—software design reviews, news groups—all sorts of ways we get feedback on the language. The feedback brings up issues, bugs, inconsistencies, irregularities. So there are things we know we want to do. They end up on the list, and then we keep iterating. We'll look at one and ask, "Do we have any new thoughts on this? No new thoughts? Well, this thing has really rotted here for several weeks, let's try to attack it for thirty minutes and see if we can get somewhere this time."

Bruce Eckel: So when something smells bad enough...

Anders Hejlsberg: Or when something smells good enough that you want to do something with it in the next release, you work on it. But I think this process is just a way to make sure nothing falls through the cracks. You put everything on that list. Something can sit on that list for a long time, and then maybe you decide you're not going to do it. But at least it gets captured, and there's a way to revisit it. It will either happen or not happen, but it won't get lost.

Bill Venners: Who was on the C# design team and what roles did they play?

Anders Hejlsberg: The original C# design team was Scott Wiltamuth, Peter Golde, Peter Sollich, Eric Gunnerson, and myself. The C# 2.0 design team is Peter Hallam, Shon Katzenberger, Todd Proebsting, and myself. Most of the credit for generics goes to Don Syme and Andrew Kennedy from Microsoft Research.

Usability Studies versus Aesthetics
Bill Venners: How much of the design of C# was based on usability research, how much on marketing choices, and how much on aesthetics?

Anders Hejlsberg: Ultimately, good language design boils down to assembling a team of people who have good taste. It boils down to programming aesthetics, as you are saying. Good taste is extremely subjective and hard to define, but you can sort of recognize it when you see it. And I don't think any number of usability studies can give you what taste gives you, because usability studies tend to be very vertical. A study might ask, "What do you think of this particular feature?" But it's not easy to ask, "What do you think of this language?" Where would you begin? How can you possibly attack that in a two hour usability study? It's just impossible.

Bruce Eckel: Somebody has to have depth of understanding.

Anders Hejlsberg: Working with a programming language is a much more immersive process. People don't really come to appreciate a programming language until they've worked with it for months. And then they may gradually realize, "Wow, this is really comfortable." You just can't do that very quickly.

That being said, we did a bunch of usability studies, but they were more vertically targeted on particular features.

Bill Venners: For example?

Anders Hejlsberg: Most of it was actually usability studies of IDE features. We might ask, "Can people understand that they right click to do this or that?" We did some usability studies for the pure language syntax itself—I think we did some with properties and events, for example—but it was not necessary really.

I don't think that you get as high a yield from usability studies for language features as for IDE features. IDEs are very interactive. You can watch users right click menu items and get good feedback. For programming languages, the question is more, "Is it conceptually understandable?" That's done very well by having a customer advisory councils, sounding boards. You want places where you can say, "Here's what we're thinking about doing for this particular new feature. What do you all think?" And you actually urge them to shoot as many holes in it as possible, because you'd much rather know before you put in the feature than after. So unless a language feature is a complete slam dunk, we tend to make use of those kinds of sounding boards. 

Next Week
Come back Monday, August 11 for part VI of a conversation with Elliotte Rusty Harold about the design of the XOM API. I am now staggering the publication of several interviews at once, to give the reader variety. The next installment of this interview with Anders Hejlsberg will appear on Monday, August 18. If you'd like to receive a brief weekly email announcing new articles at Artima.com, please subscribe to the Artima Newsletter.

Talk Back!
Have an opinion about the design principles presented in this article? Discuss this article in the News & Ideas Forum topic, The C# Design Process.

Resources
Deep Inside C#: An Interview with Microsoft Chief Architect Anders Hejlsberg:
http://windows.oreilly.com/news/hejlsberg_0800.html

A Comparative Overview of C#:
http://genamics.com/developer/csharp_comparative.htm

Microsoft Visual C#:
http://msdn.microsoft.com/vcsharp/

Anders Hejlsberg was not the first Artima interviewee to mention taste. Jim Waldo made almost an identical comment about building a team of tasteful programmers in his interview:
http://www.artima.com/intv/waldo10.html

And an entire portion of Ken Arnold's interview was devoted to design taste - Taste and Aesthetics:
http://www.artima.com/intv/taste.html

<think>我们正在讨论C# WinForms应用程序中适合在运行时使用的设计模式。用户可能希望了解那些能够动态改变应用行为或结构的模式。 根据WinForms的事件驱动特性,以及需要动态响应和灵活性,以下模式特别适用: 1. 观察者模式(Observer Pattern):WinForms本身大量使用事件(event),这就是观察者模式的实现。我们可以通过事件订阅和取消订阅在运行时动态改变行为。 2. 策略模式(Strategy Pattern):用于在运行时选择算法或行为。例如,我们可以定义一系列算法,封装它们,并使它们可以互换。 3. 状态模式(State Pattern):允许对象在其内部状态改变时改变其行为,适用于运行时状态转换影响行为的场景。 4. 命令模式(Command Pattern):将请求封装为对象,从而允许参数化客户端,并支持可撤销操作。在WinForms中,菜单命令、按钮点击等都可以使用命令模式。 5. 工厂方法模式(Factory Method Pattern)或抽象工厂模式(Abstract Factory Pattern):在运行时创建对象,而不需要指定具体类。 6. 装饰者模式(Decorator Pattern):动态地给对象添加额外的职责,比继承更灵活。 下面我们重点介绍几个在WinForms中特别有用的模式,并给出示例代码。 ### 1. 观察者模式(事件机制) WinForms内置支持观察者模式,通过事件和委托实现。例如,我们可以为一个按钮的点击事件添加多个处理程序,并在运行时动态添加或移除。 ```csharp button1.Click += new EventHandler(Button1_Click); // 订阅 button1.Click -= Button1_Click; // 取消订阅 ``` ### 2. 策略模式 假设我们有一个排序功能,需要在运行时选择不同的排序策略。 ```csharp // 策略接口 public interface ISortStrategy { void Sort(List<int> list); } // 具体策略:快速排序 public class QuickSortStrategy : ISortStrategy { public void Sort(List<int> list) { // 实现快速排序 } } // 具体策略:冒泡排序 public class BubbleSortStrategy : ISortStrategy { public void Sort(List<int> list) { // 实现冒泡排序 } } // 使用策略的上下文 public class Sorter { private ISortStrategy _strategy; public Sorter(ISortStrategy strategy) { _strategy = strategy; } public void SetStrategy(ISortStrategy strategy) { _strategy = strategy; } public void Sort(List<int> list) { _strategy.Sort(list); } } // 在WinForms中使用 private void btnSort_Click(object sender, EventArgs e) { ISortStrategy strategy; if (rbQuickSort.Checked) strategy = new QuickSortStrategy(); else strategy = new BubbleSortStrategy(); var sorter = new Sorter(strategy); sorter.Sort(data); } ``` ### 3. 状态模式 例如,一个订单对象可能有不同的状态(新建、已确认、已发货等),每个状态下处理订单的行为不同。 ```csharp public interface IOrderState { void ProcessOrder(Order order); } public class NewOrderState : IOrderState { public void ProcessOrder(Order order) { // 处理新订单 } } public class ConfirmedOrderState : IOrderState { public void ProcessOrder(Order order) { // 处理已确认的订单 } } public class Order { public IOrderState CurrentState { get; set; } public Order() { CurrentState = new NewOrderState(); } public void Process() { CurrentState.ProcessOrder(this); } } ``` ### 4. 命令模式 在WinForms中,我们可以将按钮点击等操作封装为命令对象,支持撤销和重做。 ```csharp public interface ICommand { void Execute(); void Undo(); } public class OpenFileCommand : ICommand { private string _filePath; public OpenFileCommand(string filePath) { _filePath = filePath; } public void Execute() { // 打开文件 } public void Undo() { // 撤销打开文件的操作(如关闭文件) } } // 在按钮点击事件中 private void btnOpen_Click(object sender, EventArgs e) { ICommand command = new OpenFileCommand("test.txt"); command.Execute(); // 将命令加入历史记录以便撤销 } ``` ### 5. 工厂模式 运行时根据条件创建对象。 ```csharp public interface IShape { void Draw(Graphics g); } public class Circle : IShape { public void Draw(Graphics g) { g.DrawEllipse(Pens.Black, 0, 0, 100, 100); } } public class Rectangle : IShape { public void Draw(Graphics g) { g.DrawRectangle(Pens.Black, 0, 0, 100, 50); } } public static class ShapeFactory { public static IShape CreateShape(string shapeType) { switch (shapeType) { case "Circle": return new Circle(); case "Rectangle": return new Rectangle(); default: throw new ArgumentException(); } } } // 使用 private void btnCreateShape_Click(object sender, EventArgs e) { IShape shape = ShapeFactory.CreateShape(cmbShapeType.SelectedItem.ToString()); shape.Draw(this.CreateGraphics()); } ``` ### 6. 装饰者模式 动态添加功能。例如,我们有一个基本的文本框,然后可以动态添加滚动条、边框等装饰。 ```csharp public abstract class TextBox { public abstract void Draw(); } public class BasicTextBox : TextBox { public override void Draw() { // 绘制基本文本框 } } public abstract class TextBoxDecorator : TextBox { protected TextBox _textBox; public TextBoxDecorator(TextBox textBox) { _textBox = textBox; } public override void Draw() { _textBox?.Draw(); } } public class ScrollableTextBox : TextBoxDecorator { public ScrollableTextBox(TextBox textBox) : base(textBox) { } public override void Draw() { base.Draw(); // 添加滚动条 } } // 使用 TextBox textBox = new BasicTextBox(); textBox = new ScrollableTextBox(textBox); // 动态添加滚动条 textBox.Draw(); ``` 以上这些模式都能在运行时动态改变应用的行为,非常适合WinForms应用程序。选择哪种模式取决于具体需求。 §§相关问题§§ 1. 在WinForms中如何实现观察者模式? 2. 策略模式和状态模式有什么区别? 3. 命令模式在WinForms中如何支持撤销操作? 4. 工厂模式在WinForms中有哪些应用场景? 5. 装饰者模式与继承相比有什么优势?</think>在 C# WinForms 应用程序中,以下设计模式特别适合**运行时动态实现**(即根据用户操作或程序状态动态调整行为),这些模式能有效管理界面与逻辑的交互: ### 1. **观察者模式 (Observer Pattern)** - **适用场景**:事件驱动交互(如按钮点击、数据变更通知) - **实现方式**:通过 C# 内置的 `event` 机制实现 - **优势**:解耦事件发布者和订阅者,支持运行时动态订阅/取消订阅 ```csharp // 定义事件发布者 public class DataModel { public event EventHandler DataChanged; private void OnDataChanged() => DataChanged?.Invoke(this, EventArgs.Empty); } // 窗体订阅事件(可运行时动态绑定) public partial class MainForm : Form { public MainForm(DataModel model) { model.DataChanged += (s, e) => UpdateUI(); } } ``` ### 2. **策略模式 (Strategy Pattern)** - **适用场景**:运行时切换算法或行为(如排序算法、导出格式) - **实现方式**:接口定义策略,运行时注入具体实现 ```csharp public interface IExportStrategy { void Export(DataGridView data); } // 运行时切换策略 public class ExportContext { private IExportStrategy _strategy; public void SetStrategy(IExportStrategy strategy) => _strategy = strategy; public void ExecuteExport(DataGridView data) => _strategy?.Export(data); } // 使用示例 var exporter = new ExportContext(); exporter.SetStrategy(new CsvExportStrategy()); // 运行时切换为CSV导出 exporter.ExecuteExport(dataGridView1); ``` ### 3. **状态模式 (State Pattern)** - **适用场景**:对象行为随状态改变(如编辑模式/查看模式切换) - **实现方式**:状态接口 + 具体状态类 ```csharp public interface IUIState { void Handle(Form form); } public class EditState : IUIState { public void Handle(Form form) { form.Controls.OfType<TextBox>().ToList() .ForEach(t => t.Enabled = true); // 启用所有文本框 } } // 运行时切换状态 public class FormStateContext { public IUIState CurrentState { get; set; } public void ApplyState() => CurrentState?.Handle(ownerForm); } // 使用 context.CurrentState = new EditState(); context.ApplyState(); // 动态切换到编辑模式 ``` ### 4. **命令模式 (Command Pattern)** - **适用场景**:撤销/重做、菜单操作、异步任务 - **实现方式**:将请求封装为对象 ```csharp public interface ICommand { void Execute(); void Undo(); } public class SaveCommand : ICommand { private TextBox _textBox; private string _prevText; public void Execute() { _prevText = _textBox.Text; File.WriteAllText("save.txt", _textBox.Text); } public void Undo() => _textBox.Text = _prevText; } // 命令管理(支持运行时添加) List<ICommand> commandHistory = new List<ICommand>(); buttonSave.Click += (s, e) => { var cmd = new SaveCommand(txtContent); cmd.Execute(); commandHistory.Add(cmd); // 动态记录命令 }; ``` ### 5. **工厂方法模式 (Factory Method)** - **适用场景**:运行时动态创建控件或对象 ```csharp public Control CreateControl(ControlType type) { switch (type) { case ControlType.TextBox: return new TextBox { Dock = DockStyle.Top }; case ControlType.ComboBox: return new ComboBox { DataSource = GetItems() }; default: throw new ArgumentException(); } } // 运行时动态生成 panel1.Controls.Add(CreateControl(ControlType.ComboBox)); ``` ### 6. **中介者模式 (Mediator Pattern)** - **适用场景**:复杂UI组件间通信 - **实现方式**:通过中介对象协调交互 ```csharp public class FormMediator { public void Register(Control control, Action action) { ... } public void Notify(Control sender) { // 根据sender类型触发其他控件更新 if (sender is TextBox) UpdatePreview(); } } // 控件注册中介 textBox1.TextChanged += (s, e) => mediator.Notify(textBox1); ``` ### 选择建议 | **场景** | **推荐模式** | **优势** | |-----------------------------|---------------------|----------------------------------| | 事件通知/数据绑定 | 观察者模式 | 原生事件支持,低耦合 | | 动态切换算法 | 策略模式 | 避免条件分支,易扩展 | | 界面状态转换 | 状态模式 | 状态行为集中管理 | | 撤销/重做/宏命令 | 命令模式 | 封装操作历史 | | 运行时对象创建 | 工厂方法 | 隔离创建逻辑 | | 多控件复杂交互 | 中介者模式 | 减少组件间直接依赖 | > **关键实践**:在 WinForms 中优先使用 C# 语言特性(如事件、委托)简化模式实现,避免过度设计。对于数据绑定场景,可结合 `BindingSource` 组件提升效率[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值