Standard: Qs on NET Standard, Formal Specifications, Type Equivalence, etc.

Created on 15 Jan 2019  Â·  8Comments  Â·  Source: dotnet/standard

I've started porting (rewriting) the Net Core framework to the GPU. Part of this very large task is to go through the framework and verify that it indeed satisfies the Net Standard specification because I really don't trust anything/anyone. So, I have several questions regarding Net Standard.

1) According to Microsoft documentation (https://docs.microsoft.com/en-us/dotnet/standard/net-standard), “[t]he .NET Standard is a formal specification of .NET APIs that are intended to be available on all .NET implementations. The motivation behind the .NET Standard is establishing greater uniformity in the .NET ecosystem. ECMA 335 continues to establish uniformity for .NET implementation behavior, but there's no similar spec for the .NET Base Class Libraries (BCL) for .NET library implementations.”

Q: Exactly where is the “formal specification” of the API? Is it the MD file for a particular version (e.g., https://raw.githubusercontent.com/dotnet/standard/master/docs/versions/netstandard2.0_ref.md)? Is it the collection of C# files with stub implementations (e.g., the files in https://github.com/dotnet/standard/tree/master/src/netstandard/ref)? Or, is it something else?

2) Assuming that the C# files in https://github.com/dotnet/standard/tree/master/src/netstandard/ref is the formal definition. I wrote a CSPROJ to build an assembly for the current state of the decls. Then, I wrote a program to go through a framework, following reference assemblies to implementation assemblies, and output a sorted list of all types, all methods, all attributes, for public decls. I compared the reference and implementation assemblies for Net Core with the Standard set forth in the C# code. And yes, there are some non-trivial differences, mostly because the standard is evolving.

The following are general questions of type equivalence.

Q: If there's an attribute ("[...]") on a type is in Standard, but missing on the type in Core, does Core still satisfy the Standard?

Q: If a method and/or type exists in Core, but not in Standard, does the implementation still satisfy the Standard? In other words, can an implementation provide "extra" and still satisfy Standard?

The full list of the type dump for Standard and Core assemblies is here (https://1drv.ms/f/s!Atb3HX_AxX9ZgaxT-m221N6ut285Vw).

question

All 8 comments

Q: Exactly where is the “formal specification” of the API?

It's the contents of the netstandard assembly that defines the API in ECMA335 compliant metadata. We call these things reference assemblies (basically the .NET equivalent of a C++ header file). The source code of the reference assembly is indeed https://github.com/dotnet/standard/tree/master/src/netstandard/ref, so I consider this the formal specification.

  1. Assuming that the C# files in https://github.com/dotnet/standard/tree/master/src/netstandard/ref is the formal definition. I wrote a CSPROJ to build an assembly for the current state of the decls. Then, I wrote a program to go through a framework, following reference assemblies to implementation assemblies, and output a sorted list of all types, all methods, all attributes, for public decls

Wow, that's a quite a bit of work. If you're curious, check out API Compat, it's a tool that we wrote that validates that a given implementation satisfies a given API spec.

Q: If there's an attribute ("[...]") on a type is in Standard, but missing on the type in Core, does Core still satisfy the Standard?

It depends. If the lack of the attribute can produce source/binary breaking changes then it's not. However, most attributes are only used for higher-level things (e.g. display in the property grid). I consider having them in the standard to be mostly a bug (which is a side-effect of us seeding the standard with the API definition of a particular platform). For new APIs, we try to avoid adding meaningless (or implementation specific) attributes.

Q: If a method and/or type exists in Core, but not in Standard, does the implementation still satisfy the Standard? In other words, can an implementation provide "extra" and still satisfy Standard?

Yes, platforms are allowed to expose more APIs than in .NET Core. However, in general we'll try to add these new members to future versions of the standard to align core concepts -- member differences are generally unwanted and usually only an artifact of timing.

Does this help?

Q: Exactly where is the “formal specification” of the API?

It's the contents of the netstandard assembly that defines the API in ECMA335 compliant metadata. We call these things reference assemblies (basically the .NET equivalent of a C++ header file). The source code of the reference assembly is indeed https://github.com/dotnet/standard/tree/master/src/netstandard/ref, so I consider this the formal specification.

It's still not clear to me whether the collection of C# files is the "spec", or the _ref.md file is the spec, because it's not stated anywhere. But it's really bad policy to duplicate a spec so that it's in two places because they may be out of sync. Is the doc generated from the C# files or vice versa? There are no scripts in the repos for standard, coreclr, or corefx to generate one from the other, so I assume it's done by hand, which is prone to error.

To answer this question, and to check whether there are any differences between the _ref.md files and C# files, I'm using a transformational system I wrote to generate one from the other. I'd rather spend a little extra time to verify no differences before porting System.Private.CoreLib. I know of one class that is marked abstract in Core but not in Standard, so I am not trusting anything at this point.

I'm not particularly fond of the term "reference assembly". Extending the "interface/implementation metaphor" described in the doc (https://github.com/dotnet/standard/blob/master/docs/metaphor.md), I'd rather it was called an "interface assembly" (which contains type forwarding as implemented via System.Runtime.CompilerServices.TypeForwardedTo), and the assemblies that contain the implementation as an "implementation assembly". Then Net Standard could be described as a common, interchangeable interface assembly with implementation assemblies.

I'm not particularly fond of the term "reference assembly".

For good or ill, that was the name chosen a long time ago when the .NET Framework first decided to create stub assemblies that compilers should reference. This is also what the compiler calls it (-refonly Produce a reference assembly in place of the main output) and the documentation.

Is the doc generated from the C# files or vice versa?

The doc is generated from the C# files (or rather the assembly created from them)

It's still not clear to me whether the collection of C# files is the "spec", or the _ref.md file is the spec, because it's not stated anywhere.

The source is the authoritative definition of .NET Standard. It's not stated anywhere because (1) it's obvious to us on the team and (2) nobody asked the question yet. Your point is well take though :-)

But it's really bad policy to duplicate a spec so that it's in two places because they may be out of sync. Is the doc generated from the C# files or vice versa?

The Markdown files are generated by an internal tool. It's manual, because I only do it when we're about to announce a release.

I'm not particularly fond of the term "reference assembly".

Well, as @danmosemsft said, this term is in use for 14 years now and was invented long before .NET Standard was a thing.

Extending the "interface/implementation metaphor" described in the doc (https://github.com/dotnet/standard/blob/master/docs/metaphor.md), I'd rather it was called an "interface assembly" (which contains type forwarding as implemented via System.Runtime.CompilerServices.TypeForwardedTo), and the assemblies that contain the implementation as an "implementation assembly"

I'm not a fan of the term interface assembly because interface has already a meaning in .NET and it's quite specific. In any case, I'm not sure changing terminology at this point is worth it. For most .NET developers this is implementation jargon as very few people will ever have to understand reference assemblies or even implement .NET Standard.

Is the doc generated from the C# files or vice versa?

The doc is generated from the C# files (or rather the assembly created from them)

It would have been nice if the _ref.md file had a line it in saying "Generated on ... from tool ... version ... from input assembly .... built ... version ... Do not hand edit." I looked in all files in standard, coreclr, corefx, corert, and mono, for anything that contained the string "_ref.md". Thus the question.

It would have been nice if the _ref.md file had a line it in saying "Generated on ... from tool ... version ... from input assembly .... built ... version ... Do not hand edit."

That's a good point. I'll update the files.

Was this page helpful?
0 / 5 - 0 ratings