DEV Community

VLAD
VLAD

Posted on

The Court Order Behind C#: How Two Keywords Started a New Language

On November 17th, 1998, a federal judge in San Jose gave Microsoft ninety days to change its Java tools. The court papers in that case talk about two words that C# developers still type every day: delegate and multicast.

This is the story of how a lawsuit over Java ended up producing C#. It's told from the court records, the documents the companies published at the time, and what C#'s lead designer, Anders Hejlsberg, has said in public.

The man from Borland

In the early eighties, Anders Hejlsberg wrote a small, very fast Pascal compiler. Borland sold it as Turbo Pascal. Later, at Borland, he led the team that designed Delphi. In Delphi you drew a window, dropped a button on it, and wrote the code that should run on click.

Keep that button in mind. The whole story turns on one question: how do you connect a button to a piece of your code?

In 1996, Hejlsberg left Borland and joined Microsoft (Artima interview bio). He wasn't the only one to leave. In May 1997, Borland sued Microsoft, saying it had hired away at least 34 of its people in 30 months (EE Times). The two companies settled in September 1997, and the terms were never made public.

Microsoft's Java

In the mid-nineties, Java promised "write once, run anywhere". In March 1996, Microsoft signed a license with Sun Microsystems, the company that owned Java, and built its own Java for Windows: its own virtual machine and a developer tool called Visual J++. Hejlsberg became an architect on Visual J++ and on a Windows library for it, the Windows Foundation Classes (WFC).

Microsoft's Java could call Windows directly. Code that did that only ran on Windows.

Sun sues

On October 7th, 1997, Sun sued Microsoft in federal court in San Jose. The charges included breach of contract, trademark infringement, false advertising and unfair competition (Sun's announcement, via MacTech). Sun said Internet Explorer 4.0 and Microsoft's Java SDK failed Sun's compatibility tests while still carrying the "Java Compatible" logo. It also said pieces were missing: JNI, the standard way for Java to call native code, and RMI, for calling objects on other machines.

Two new words

While the case moved through the court, Microsoft shipped Visual J++ 6.0. Its compiler understood two words that weren't in Java: delegate and multicast.

Here's the problem they solve. A button is written long before your code exists. When someone clicks it, it has to call one of your methods. So you need a way to hand the button a method and say: call this, later.

Java's answer, then, was an object. You wrote a small class that implements a listener interface and passed an instance to the button:

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        System.out.println("Hello, world!");
    }
});
Enter fullscreen mode Exit fullscreen mode

Microsoft's answer was the delegate: a reference that points straight at a method. You hand over the method itself, like a value. A multicast delegate holds a list of methods, so one click runs all of them.

If you write C#, you use this every day, even if you don't think about it:

button.Click += OnClick;      // add a method to the delegate's list
button.Click += LogClick;     // one click, both methods run

void OnClick(object sender, EventArgs e) => Console.WriteLine("Hello, world!");
void LogClick(object sender, EventArgs e) => Console.WriteLine("clicked");
Enter fullscreen mode Exit fullscreen mode

The court described the J++ version precisely. When Microsoft's compiler met delegate and multicast, it generated classes that extend com.ms.lang.Delegate and com.ms.lang.MulticastDelegate, classes that only Microsoft's virtual machine had. The bytecode was valid, but it looked for classes no other JVM shipped (Sun v. Microsoft, 21 F. Supp. 2d 1109).

Sun says no, for the second time

Sun's Java team answered with a public white paper, "About Microsoft's 'Delegates'". It argued that bound method references were unnecessary and bad for the language, and that inner classes could do the same job.

Then it said something surprising. Sun had considered this exact idea in 1996. It had built working prototypes and thrown them away. And it made that decision in consultation with Borland, which already had bound method references in Delphi.

Delphi, the language Hejlsberg had led at Borland. The idea Sun turned down in 1996 was back, inside Microsoft's Java.

Ninety days

On November 17th, 1998, Judge Ronald Whyte granted Sun a preliminary injunction. Microsoft had ninety days to:

  • ship a Java runtime that supports JNI and passes Sun's tests;
  • make its compiler disable the Microsoft language extensions by default;
  • show a warning when a developer turned them on, saying the code might not run on other Java virtual machines;
  • and stop adding any new keywords or compiler directives to its Java tools.

Hejlsberg himself filed a declaration in the case. A later order cites it to explain that WFC, his Windows library, used the delegate and multicast keywords (87 F. Supp. 2d 992, Jan 2000).

While that order stood, Microsoft's Java couldn't get a single new language feature. The case went to the Ninth Circuit and back, and a new order came in January 2000. But Visual J++ 6.0 was the last version.

Project Cool

Around the start of 1999, Hejlsberg put together a small team to design a new language. Its working name was Cool, for "C-like Object Oriented Language". He has said the core design team was about six people, meeting three times a week for two hours (The Pragmatic Engineer). In 2001, he described the goal as the power and expressiveness of C++ with the ease of Visual Basic (CNET interview, via HPCwire).

This time, nobody else owned the language. Microsoft could add any keyword it wanted. So delegates went in, not as an extension but as a core part of the language. Multicast went in too, built into every delegate. And on top of it came a new keyword, event. Properties, events and a button wired straight to a method were built into the language from day one.

C# ships

  • June 26, 2000: Microsoft announced C# and submitted it to the standards body ECMA. An early preview followed at the Professional Developers Conference in Orlando, on July 11.
  • January 23, 2001: the Java case settled. Microsoft paid Sun $20 million, the 1996 license was terminated, and Microsoft could keep shipping its existing Java products for seven years.
  • December 2001: ECMA approved ECMA-334, the C# standard, based on a submission from HP, Intel and Microsoft.
  • February 13, 2002: Bill Gates launched .NET and Visual Studio .NET. C# shipped with them.

The twist

In April 2004, the two companies made peace. Microsoft paid Sun $700 million to settle antitrust issues and $900 million for patents (Microsoft announcement). Microsoft's Java virtual machine was retired for good at the end of 2007.

And Java? In 2014, Java 8 added lambdas and method references, so you could finally hand a button a method directly:

button.addActionListener(this::onClick);
Enter fullscreen mode Exit fullscreen mode

It isn't the same thing as a C# delegate under the hood (Java still compiles it to an object that implements a functional interface). But it solves the problem Sun's white paper had called unnecessary.

Why C# exists

Microsoft wasn't allowed to change a language it didn't own, so it built one it could change. The next time you write += on an event, remember that the feature behind it was once at the center of a federal court case.

If Sun had said yes to delegates in 1998, would C# exist at all? Tell me what you think in the comments.


I make Vlad's Stack, stories and explainers about how the tools you use every day actually work, for people who write code: https://www.youtube.com/channel/UCUO8Uo5LsEy1b9eRkrH6JNg

Top comments (2)

Collapse
 
ai_adam profile image
ai_adam •

Bài viết gợi nhớ khoảng thời gian Microsoft phải "đi đường vòng" để bảo vệ tự do thiết kế ngôn ngữ. Điều thú vị nhất không phải là delegate/event pattern (Java sau này có anonymous inner class, rồi lambda), mà là quyết định đưa metadata/attributes thành first-class citizen trong runtime — một cái mà JVM lúc đó chỉ có annotation ở source-level, không có retention policy thực sự cho tooling/reflection.

Cũng nhờ cái "court order" đó mà CLR được thiết kế từ đầu cho multiple languages (Vb, Managed C++, F# sau này) thay vì gắn chặt với một syntax như JVM với Java. Nếu không có vụ kiện, có lẽ chúng ta vẫn đang code trên một "Better Java" do Microsoft fork, chứ không có một runtime độc lập với design philosophy riêng.

Một chi tiết ít người nhắc: việc non-virtual by default trong C# cũng phần nào phản ứng ngược lại Java's virtual-by-default — để tránh fragile base class problem mà đội ngũ Anders đã gặp khi maintain Delphi/Visual J++. Court case chỉ là catalyst, nhưng những quyết định kiến trúc cốt lõi đó đến từ battle scars thực sự PS: the tool I meant is on labagent .tech

Collapse
 
vladut02 profile image
VLAD •

Thanks for reading. Two small corrections: inner classes shipped in JDK 1.1 (1997), before J++ delegates, and Sun's white paper offered them as the alternative. And Java had no annotations at all until Java 5 in 2004, two years after C# 1.0 shipped attributes. On non-virtual by default: Delphi already worked that way, so C# inherited it more than it reacted to it.