1
Suggestions and Requests / Declared and Referenced Namespace
« on: May 09, 2003, 06:09:00 am »
Namespaces and C# Code Generation
------------------------------------------------
An EA improvement appears needed to enhance the use of Namespaces in C# and to avoid hand-fixup of generated code. The following analysis of the issue should help to understand and perhaps clarify things.
Without this feature, it appears that there may be significant consequences for generated code, if an external supplier of classes revises their external class library.
There are two aspects to consider:
1. the declaration of new classes in namespaces, and
2. the reference to previously declared classes.
Declaration of a class happens once, but reference to a class happens many times.
Class Declaration
----------------------
Declaration of a class always happens in an absolute namespace, eg.
Absolute: N1.N2. ... .Nj.SomeClass.
Current EA code generation options permit setting a package Ni as namespace root, which causes the generated declaration to take a relative form
Relative: Ni.Ni+1. ... .Nj.SomeClass
(Where N1 is not absolute but is implied as being in or relative to another namespace, we really have a relative qualification of form Relative:, which is covered further below).
In the relative namespace-qualified declaration of SomeClass, there is always some assumed further absolute namespace prefix, which EA does not generate. The EA "Set as Namespace Root" is used to accomplish this relative form.
The reason for the namespace prefix of SomePrefix.SomeClass is to distinguish it from SomeOtherPrefix.SomeClass, where SomeClass has the same spelling. That is why namespaces where invented, here and in other areas such as Xml. The distinct prefixes disambiguate the ambiguous SomeClass spelling into a specific class with a uniquely identified namespace prefix.
Class Reference
--------------------
Class reference happens many times, for example in multiple declarations of SomeClass instances. In order to save typing, C# provides the "Using SomePrefix;" construct so that you do not have to type the full SomePrefix.SomeClass for every class reference.
The Problem
---------------
Unfortunately, overuse of the "Using" feature can introduce ambiguities where SomeClass can resolve to different SomePrefix namespaces in which SomeClass has been declared. Consider
Using Namespace1;
Using Namespace2;
public MyClass: SomeClass ...
where both Namespace1 and Namespace2 declare a (different) SomeClass spelled the same way.
This is a compile-time error.
A Solution
----------------
A solution is to disambiguate the SomeClass reference by providing sufficient (relative or absolute) namespace prefix to achieve unique identification to the desired class in the desired namespace.
EA provides the "Set as Namespace Root" mechanism as a control that operates on the declarative side of the code generator, and permits control of namespace prefix generation for class declaration. This is really a "Set as Namespace (Declarative) Root" control -- it controls the generation of the class declarations. The appropriate namespace declarations are emitted, before the class declaration is emitted.
What is missing is an additional "Set as Namespace (Referencing) Root" control that permits control of namespace prefix generation for class references. This control must control both the generation of the appropriate "Using" statements, and the generation of sufficient relative and / or absolute namespace prefixes for class references to ensure that the reference is unambiguous. Any generated reference to SomeClass must carry sufficient namespace prefix to identify uniquely to a Namespace Referencing Root.
For example, The System.xxx namespaces would generally not be set to be a Namespace Referencing Root(s), thereby ensuring that any generated reference to any System.xxx.SomeClass is always absolute. This is essential, since one can not be sure that Microsoft will not at some future time release a SomeClass as System.xxx.SomeClass that comes into conflict with OurNameSpacePrefix.SomeClass that we have constructed. Our code of form:
Using System.xxx;
Using OurNameSpacePrefix;
... many SomeClass references ...
would break under these conditions, with potentially significant consequences.
Conclusion
-------------
In addition to the current "Set as (Declarative) Namespace Root" control that controls the generation of declarations, it appears EA requires an additional "Set as (Referencing) Namespace Root" control that controls the generation of references. Manual code fixups are otherwise potentially required.
For example, you would probably always set System as a namespace referencing root, so that any reference to any System.xxx.SomeClass would always be generated as an absolute System.xxx.SomeClas reference. That way, you can be sure that any locally declared SomeClass will not come into conflict with a (future) System.xxx.SomeClass that Microsoft might release.
For another example, you would probably always set any other externally defined namespace whose classes you import and use as a namespace referencing root. That way, you can be sure that any locally declared SomeClass will not come into conflict with a (future) External.xxx.SomeClass when the external supplier revises their delivered class library.
Alternative (and perhaps cleaner) solutions may exist, and perhaps I missed something and these solutions are already there. If so, could you point me in the right direction?
Thanks
Rainer
------------------------------------------------
An EA improvement appears needed to enhance the use of Namespaces in C# and to avoid hand-fixup of generated code. The following analysis of the issue should help to understand and perhaps clarify things.
Without this feature, it appears that there may be significant consequences for generated code, if an external supplier of classes revises their external class library.
There are two aspects to consider:
1. the declaration of new classes in namespaces, and
2. the reference to previously declared classes.
Declaration of a class happens once, but reference to a class happens many times.
Class Declaration
----------------------
Declaration of a class always happens in an absolute namespace, eg.
Absolute: N1.N2. ... .Nj.SomeClass.
Current EA code generation options permit setting a package Ni as namespace root, which causes the generated declaration to take a relative form
Relative: Ni.Ni+1. ... .Nj.SomeClass
(Where N1 is not absolute but is implied as being in or relative to another namespace, we really have a relative qualification of form Relative:, which is covered further below).
In the relative namespace-qualified declaration of SomeClass, there is always some assumed further absolute namespace prefix, which EA does not generate. The EA "Set as Namespace Root" is used to accomplish this relative form.
The reason for the namespace prefix of SomePrefix.SomeClass is to distinguish it from SomeOtherPrefix.SomeClass, where SomeClass has the same spelling. That is why namespaces where invented, here and in other areas such as Xml. The distinct prefixes disambiguate the ambiguous SomeClass spelling into a specific class with a uniquely identified namespace prefix.
Class Reference
--------------------
Class reference happens many times, for example in multiple declarations of SomeClass instances. In order to save typing, C# provides the "Using SomePrefix;" construct so that you do not have to type the full SomePrefix.SomeClass for every class reference.
The Problem
---------------
Unfortunately, overuse of the "Using" feature can introduce ambiguities where SomeClass can resolve to different SomePrefix namespaces in which SomeClass has been declared. Consider
Using Namespace1;
Using Namespace2;
public MyClass: SomeClass ...
where both Namespace1 and Namespace2 declare a (different) SomeClass spelled the same way.
This is a compile-time error.
A Solution
----------------
A solution is to disambiguate the SomeClass reference by providing sufficient (relative or absolute) namespace prefix to achieve unique identification to the desired class in the desired namespace.
EA provides the "Set as Namespace Root" mechanism as a control that operates on the declarative side of the code generator, and permits control of namespace prefix generation for class declaration. This is really a "Set as Namespace (Declarative) Root" control -- it controls the generation of the class declarations. The appropriate namespace declarations are emitted, before the class declaration is emitted.
What is missing is an additional "Set as Namespace (Referencing) Root" control that permits control of namespace prefix generation for class references. This control must control both the generation of the appropriate "Using" statements, and the generation of sufficient relative and / or absolute namespace prefixes for class references to ensure that the reference is unambiguous. Any generated reference to SomeClass must carry sufficient namespace prefix to identify uniquely to a Namespace Referencing Root.
For example, The System.xxx namespaces would generally not be set to be a Namespace Referencing Root(s), thereby ensuring that any generated reference to any System.xxx.SomeClass is always absolute. This is essential, since one can not be sure that Microsoft will not at some future time release a SomeClass as System.xxx.SomeClass that comes into conflict with OurNameSpacePrefix.SomeClass that we have constructed. Our code of form:
Using System.xxx;
Using OurNameSpacePrefix;
... many SomeClass references ...
would break under these conditions, with potentially significant consequences.
Conclusion
-------------
In addition to the current "Set as (Declarative) Namespace Root" control that controls the generation of declarations, it appears EA requires an additional "Set as (Referencing) Namespace Root" control that controls the generation of references. Manual code fixups are otherwise potentially required.
For example, you would probably always set System as a namespace referencing root, so that any reference to any System.xxx.SomeClass would always be generated as an absolute System.xxx.SomeClas reference. That way, you can be sure that any locally declared SomeClass will not come into conflict with a (future) System.xxx.SomeClass that Microsoft might release.
For another example, you would probably always set any other externally defined namespace whose classes you import and use as a namespace referencing root. That way, you can be sure that any locally declared SomeClass will not come into conflict with a (future) External.xxx.SomeClass when the external supplier revises their delivered class library.
Alternative (and perhaps cleaner) solutions may exist, and perhaps I missed something and these solutions are already there. If so, could you point me in the right direction?
Thanks
Rainer