[[Property:modification_date|Mon, 23 Oct 2023 15:36:40 GMT]]
[[Property:publication_date|Wed, 27 Sep 2023 19:33:07 GMT]]
[[Property:title|Eiffel for .NET Integration]]
[[Property:weight|3]]
[[Property:uuid|fe8a6a7d-4590-0db2-d59a-307082b18ecc]]
==Differences between Eiffel and Eiffel for .NET==
===Limitation of Eiffel for .NET in version 23.09===
Most of the Eiffel mechanisms are supported in 23.09.
Eiffel for .NET supports:
* Multiple Inheritance
* Design By Contract
* Exception handling
* Genericity
* Covariance
* Compilation of any existing Eiffel libraries as long as it does not include C externals that call into the Eiffel Software C runtime
* the [[Concurrent_programming_with_SCOOP|SCOOP]] capability is not support by the Eiffel.NET compiler
However, there are a few limitations that are described later in this documentation.
===Added to Eiffel and Eiffel for .NET===
The following syntax can be used to declare .NET custom attributes on Eiffel entities (features and classes):
empty: BOOLEAN
note
description: "Is Current empty?"
metadata: create {OBSOLETE_ATTRIBUTE}.make ("Use `is_empty' instead") end
obsolete
"Use is_empty instead"
do
Result := is_empty
end
The previous example shows the declaration of the obsolete feature empty
. The custom attribute defined by OBSOLETE_ATTRIBUTE
is used to ensure that any consumer of the resulting assembly will see the feature as being obsolete. The custom attribute is defined in the note
clause metadata
. The definition consists of a creation expression that creates the custom attribute with the right parameters.
Using the metadata
tag is the most general way of applying a custom attribute. There are however some variations that are explained below:
*metadata
: most general way, it applies a custom attribute to both the class and interface generated by the Eiffel compiler.
*class_metadata
: applies only to the class generated by the Eiffel compiler (mostly for advanced users).
*interface_metadata
: applies only to the interface generated by the Eiffel compiler (mostly for advanced users).
*property_metadata
: applies a custom attribute to the associated property generated by the Eiffel compiler for a query.
*assembly_metadata
: applies a custom attribute for the current assembly. It only works when present in the Eiffel system root class note
clause.
==Differences between Eiffel for .NET and .NET==
===Covariance===
The CLR (Common Language Runtime) does not support [[ET: Inheritance#Covariance and anchored declarations|covariance]] due to a different view of type safety (the issue is known known as a polymorphic [[ET: Inheritance#Catcalls|catcall]] in Eiffel). Catcalls are possible (although very rare) in Eiffel but not in .NET.
Eiffel for .NET implements a safe variant of covariance that will always perform a check on the types to avoid a catcall. So when a catcall is going to be performed a `Invalid Cast Exception` will be raised by the CLR instead of an unexpected behavior as is the default behavior in classic Eiffel (i.e., the behavior without catcall detection explicitly enabled).
Another advantage of Eiffel for .NET's implementation of covariance is that it can be easily understood by CLS-compliant consumer tools. These tools will actually benefit from the Eiffel for .NET covariance.
===Handling Eiffel and .NET genericity===
As noted above, Eiffel for .NET fully supports the powerful genericity mechanism of the Eiffel language. The interface with .NET's own genericity mechanism is, however, not complete in version 23.09. Specifically:
* Generic classes in Eiffel will not yield generic classes in .NET. Instead, each generic derivation of a given Eiffel class will yield a different .NET class. So if we have a generic Eiffel class LIST [G]
, the type LIST [ANY]
will yield a .NET class LIST_ANY
, and the type LIST [INTEGER]
will yield a class LIST_Int32
.
* If you want to use a generic .NET class (for example in C#), you have to use special techniques as described next.
{{Recommended|Read the [[Workaround Eiffel .NET limitations]] page to learn how to workaround such limitation. }}
===Enum types===
Eiffel for .NET supports .NET enum types implicitly. From the point of view of Eiffel, they are just considered as expanded classes. The only difference is in the code generation. Eiffel for .NET cannot declare new enum types yet.
===ByRef===
Eiffel does not have the notion of `byref` argument passing. At the moment, Eiffel for .NET cannot call nor can it redefine a feature that has a byref argument.
=== Type with "init" only setters===
Eiffel currently does not support the special `init` property that is only initialized in a block of code as part of the object initialization. More details can be found in the [https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/init C# 9.0 proposal]
Note: {{inline-info|this section is mostly for .NETCore 6.0 and above}}.
'''Workaround''':
A potential workaround is to create a C# library that uses a Factory pattern to build the required instance.
===Execution and publishing ===
Currently the EiffelStudio debugger supports only the Eiffel .NET Framework application (i.e .Net framework v4.0).
For .NETCore (net6.0, net7.0, ...) it is not yet available within the EiffelStudio IDE.
{{recommended|Learn more how to publish, execute, debug, ... the Eiffel .NETCore application, with the [[Eiffel .NETCore execution]] page.}}
== Environment variables for .NETCore ==
The Eiffel compiler sets a few environment variables available in the ECF files and allows to write ECF file without hardcoded version numbers.
* '''ISE_DOTNET_FRAMEWORK''': location of the default .NET runtime directory (parent of System.dll, System.Runtime.dll, ...)
* '''ISE_DOTNET_PLATFORM''': for a .NET project it contains either "framework", or "netcore" to distinguish between .NET Framework (v4.0) and .NETCore solutions (net6.0, neet7.0, ...)
* '''ISE_DOTNET_PACKS''': location to the .NETCore "packs" directory (parent of .NETCore '''reference'' runtimes)
* '''ISE_DOTNET_PACKS''': location to the .NETCore "shared" directory (parent of .NETCore implementation runtimes)
* '''ISE_DOTNET_TFM''': .NETCore TFM (Target Framework Moniker) , for instance "net6", "net7", ...
* '''ISE_DOTNET_VERSION''': .NETCore runtime precise version number (for instance 7.0.11)