You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Introduce term "identity convertible" for types that aren't the same type, but have an identity conversion (#985)
* first commit: dynamic and object
Introduce and define the term "runtime interchangeable" in the types clause.
Where applicable, replace the phrases "the same type" and "equivalent types" with the phrase "runtime interchangeable."
* 2nd commit:
Prohibit `dynamic` as a base class.
* commit three: Move definition
Move and expand the definition of *runtime interchangeable* to the conversions chapter, and expand its definition to include tuples and constructed generic types.
* use runtime interchangeable
Sweep the standard for instances of "identity conversion" and replace with "runtime interchangeable" in those instances where the meaning was specifically one of the types that aren't the same, but have an identity conversion.
* one more edit pass
* proofread
* Update standard/types.md
Co-authored-by: Jon Skeet <[email protected]>
* Update standard/types.md
Co-authored-by: Jon Skeet <[email protected]>
* Rephrase paragraph.
* update wording on closed generic types
* Apply suggestions from code review
Co-authored-by: Neal Gafter <[email protected]>
* updates from committee
- Remove normative text on nested tuples and identity conversions.
- Add an example that demonstrates the nature of nested tuples being identity convertible when each member is identity convertible.
- Replace "runtime interchangeable" with "identity convertible".
- Add text that all identity conversions are symmetric.
* fix test runner
* respond to feedback.
* Apply suggestions from code review
Co-authored-by: Jon Skeet <[email protected]>
* Apply suggestions from code review
Co-authored-by: Jon Skeet <[email protected]>
---------
Co-authored-by: Jon Skeet <[email protected]>
Co-authored-by: Neal Gafter <[email protected]>
Copy file name to clipboardExpand all lines: standard/classes.md
+2-2
Original file line number
Diff line number
Diff line change
@@ -233,7 +233,7 @@ The base class specified in a class declaration can be a constructed class type
233
233
234
234
Thedirectbaseclassof a class type shall be at least as accessible as the class type itself ([§7.5.5](basic-concepts.md#755-accessibility-constraints)). For example, it is a compile-time error for a public class to derive from a private or internal class.
235
235
236
-
The direct base class of a class type shall not be any of the following types: `System.Array`, `System.Delegate`, `System.Enum`, or`System.ValueType`. Furthermore, agenericclassdeclarationshallnotuse `System.Attribute` asadirectorindirectbaseclass ([§22.2.1](attributes.md#2221-general)).
236
+
The direct base class of a class type shall not be any of the following types: `System.Array`, `System.Delegate`, `System.Enum`, `System.ValueType`orthe `dynamic` type. Furthermore, agenericclassdeclarationshallnotuse `System.Attribute` asadirectorindirectbaseclass ([§22.2.1](attributes.md#2221-general)).
Forthepurposesofconversion, thetypes `object` and `dynamic` areconsideredequivalent.
74
+
Forthepurposesofconversion, thetypes `object` and `dynamic` areidentityconvertible (§10.2.2).
75
75
76
76
However, dynamicconversions ([§10.2.10](conversions.md#10210-implicit-dynamic-conversions) and [§10.3.8](conversions.md#1038-explicit-dynamic-conversions)) applyonlytoexpressionsoftype `dynamic` ([§8.2.4](types.md#824-the-dynamic-type)).
>Thetypesoftuples `t1`, `t2` and `t3` allhavetwoelements:an `int` followedbya `string`. Tupleelementtypesmaythemselvesbytuples, asin `t4`, `t5`, and `t6`. Anidentityconversionexistsbetweeneachpairofcorrespondingelementtypes, includingnestedtuples, thereforeanidentityconversionexistsbetweenthetypesoftuples `t4`, `t5`, and `t6`.
111
+
>
112
+
>*endexample*
113
+
114
+
Allidentityconversionsaresymmetric. Ifanidentityconversionexistsfrom `T₁` to `T₂`, thenanidentityconversionexistsfrom `T₂` to `T₁`. Twotypesare*identityconvertible*whenanidentityconversionexistsbetweentwotypes.
87
115
88
116
Inmostcases, anidentityconversionhasnoeffectatruntime. However, sincefloatingpointoperationsmaybeperformedathigherprecisionthanprescribedbytheirtype ([§8.3.7](types.md#837-floating-point-types)), assignmentoftheirresultsmayresultinalossofprecision, andexplicitcastsareguaranteedtoreduceprecisiontowhatisprescribedbythetype ([§12.9.7](expressions.md#1297-cast-expressions)).
89
117
@@ -374,7 +402,7 @@ Explicit conversions can occur in cast expressions ([§12.9.7](expressions.md#12
Copy file name to clipboardExpand all lines: standard/expressions.md
+2-2
Original file line number
Diff line number
Diff line change
@@ -245,7 +245,7 @@ An operation of the form `«op» x` or `x «op»`, where «op» is an overloada
245
245
An operation of the form `x «op» y`, where «op» is an overloadable binary operator, `x` is an expression of type `X`, and `y` is an expression of type `Y`, is processed as follows:
246
246
247
247
- The set of candidate user-defined operators provided by `X` and `Y` for the operation `operator «op»(x, y)` is determined. The set consists of the union of the candidate operators provided by `X` and the candidate operators provided by `Y`, each determined using the rules of [§12.4.6](expressions.md#1246-candidate-user-defined-operators). For the combined set, candidates are merged as follows:
248
-
- If `X` and `Y` are the same type, or if `X` and `Y` are derived from a common base type, then shared candidate operators only occur in the combined set once.
248
+
- If `X` and `Y` are identity convertible, or if `X` and `Y` are derived from a common base type, then shared candidate operators only occur in the combined set once.
249
249
- If there is an identity conversion between `X` and `Y`, an operator `«op»Y` provided by `Y` has the same return type as an `«op»X` provided by `X` and the operand types of `«op»Y` have an identity conversion to the corresponding operand types of `«op»X` then only `«op»X` occurs in the set.
250
250
- If the set of candidate user-defined operators is not empty, then this becomes the set of candidate operators for the operation. Otherwise, the predefined binary `operator «op»` implementations, including their lifted forms, become the set of candidate operators for the operation. The predefined implementations of a given operator are specified in the description of the operator. For predefined enum and delegate operators, the only operators considered are those provided by an enum or delegate type that is the binding-time type of one of the operands.
251
251
- The overload resolution rules of [§12.6.4](expressions.md#1264-overload-resolution) are applied to the set of candidate operators to select the best operator with respect to the argument list `(x, y)`, and this operator becomes the result of the overload resolution process. If overload resolution fails to select a single best operator, a binding-time error occurs.
@@ -4406,7 +4406,7 @@ The operation is evaluated as follows:
4406
4406
1. Otherwise, `D` is `R`.
4407
4407
1. The result depends on `D` and `T` as follows:
4408
4408
1. If `T` is a reference type, the result is `true` if:
4409
-
-`D` and `T` are the same type,
4409
+
-an identity conversion exists between `D` and `T`,
4410
4410
-`D` is a reference type and an implicit reference conversion from `D` to `T` exists, or
4411
4411
- Either: `D` is a value type and a boxing conversion from `D` to `T` exists.
4412
4412
Or: `D` is a value type and `T` is an interface type implemented by `D`.
@@ -666,12 +666,13 @@ The API surface provided by `Expression<TDelegate>` is implementation-specific b
666
666
667
667
The type `dynamic` uses dynamic binding, as described in detail in [§12.3.2](expressions.md#1232-binding-time), as opposed to static binding which is used by all other types.
668
668
669
-
`dynamic` is considered identical to `object` except in the following respects:
669
+
The type `dynamic` is considered identical to `object` except in the following respects:
670
670
671
671
- Operations on expressions of type `dynamic` can be dynamically bound ([§12.3.3](expressions.md#1233-dynamic-binding)).
672
672
- Type inference ([§12.6.3](expressions.md#1263-type-inference)) will prefer `dynamic` over `object` if both are candidates.
673
673
-`dynamic` cannot be used as
674
674
- the type in an *object_creation_expression* ([§12.8.16.2](expressions.md#128162-object-creation-expressions))
675
+
- a *class_base* (§15.2.4)
675
676
- a *predefined_type* in a *member_access* ([§12.8.7.1](expressions.md#12871-general))
676
677
- the operand of the `typeof` operator
677
678
- an attribute argument
@@ -681,10 +682,13 @@ The type `dynamic` uses dynamic binding, as described in detail in [§12.3.2](ex
681
682
682
683
Because of this equivalence, the following holds:
683
684
684
-
- There is an implicit identity conversion between `object` and `dynamic`, and between constructed types that are the same when replacing `dynamic` with `object`.
685
+
- There is an implicit identity conversion
686
+
- between `object` and `dynamic`
687
+
- between constructed types that are the same when replacing `dynamic` with `object`
688
+
- between tuple types that are the same when replacing `dynamic` with `object`
685
689
- Implicit and explicit conversions to and from `object` also apply to and from `dynamic`.
686
690
- Signatures that are the same when replacing `dynamic` with `object` are considered the same signature.
687
-
- The type `dynamic` is indistinguishable from `object` at run-time.
691
+
- The type `dynamic` is indistinguishable from the type `object` at run-time.
688
692
- An expression of the type `dynamic` is referred to as a ***dynamic expression***.
0 commit comments