本文整理汇总了C#中Microsoft.CSharp.RuntimeBinder.Semantics.CType.IsAggregateType方法的典型用法代码示例。如果您正苦于以下问题:C# CType.IsAggregateType方法的具体用法?C# CType.IsAggregateType怎么用?C# CType.IsAggregateType使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Microsoft.CSharp.RuntimeBinder.Semantics.CType
的用法示例。
在下文中一共展示了CType.IsAggregateType方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: CheckAccess2
public virtual ACCESSERROR CheckAccess2(Symbol symCheck, AggregateType atsCheck, Symbol symWhere, CType typeThru)
{
Debug.Assert(symCheck != null);
Debug.Assert(atsCheck == null || symCheck.parent == atsCheck.getAggregate());
Debug.Assert(typeThru == null ||
typeThru.IsAggregateType() ||
typeThru.IsTypeParameterType() ||
typeThru.IsArrayType() ||
typeThru.IsNullableType() ||
typeThru.IsErrorType());
#if DEBUG
switch (symCheck.getKind())
{
default:
break;
case SYMKIND.SK_MethodSymbol:
case SYMKIND.SK_PropertySymbol:
case SYMKIND.SK_FieldSymbol:
case SYMKIND.SK_EventSymbol:
Debug.Assert(atsCheck != null);
break;
}
#endif // DEBUG
ACCESSERROR error = CheckAccessCore(symCheck, atsCheck, symWhere, typeThru);
if (ACCESSERROR.ACCESSERROR_NOERROR != error)
{
return error;
}
// Check the accessibility of the return CType.
CType CType = symCheck.getType();
if (CType == null)
{
return ACCESSERROR.ACCESSERROR_NOERROR;
}
// For members of AGGSYMs, atsCheck should always be specified!
Debug.Assert(atsCheck != null);
if (atsCheck.getAggregate().IsSource())
{
// We already check the "at least as accessible as" rules.
// Does this always work for generics?
// Could we get a bad CType argument in typeThru?
// Maybe call CheckTypeAccess on typeThru?
return ACCESSERROR.ACCESSERROR_NOERROR;
}
// Substitute on the CType.
if (atsCheck.GetTypeArgsAll().size > 0)
{
CType = SymbolLoader.GetTypeManager().SubstType(CType, atsCheck);
}
return CheckTypeAccess(CType, symWhere) ? ACCESSERROR.ACCESSERROR_NOERROR : ACCESSERROR.ACCESSERROR_NOACCESS;
}
示例2: GetBestAccessibleType
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// RUNTIME BINDER ONLY CHANGE
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
internal bool GetBestAccessibleType(CSemanticChecker semanticChecker, BindingContext bindingContext, CType typeSrc, out CType typeDst)
{
// This method implements the "best accessible type" algorithm for determining the type
// of untyped arguments in the runtime binder. It is also used in method type inference
// to fix type arguments to types that are accessible.
// The new type is returned in an out parameter. The result will be true (and the out param
// non-null) only when the algorithm could find a suitable accessible type.
Debug.Assert(semanticChecker != null);
Debug.Assert(bindingContext != null);
Debug.Assert(typeSrc != null);
typeDst = null;
if (semanticChecker.CheckTypeAccess(typeSrc, bindingContext.ContextForMemberLookup()))
{
// If we already have an accessible type, then use it. This is the terminal point of the recursion.
typeDst = typeSrc;
return true;
}
// These guys have no accessibility concerns.
Debug.Assert(!typeSrc.IsVoidType() && !typeSrc.IsErrorType() && !typeSrc.IsTypeParameterType());
if (typeSrc.IsParameterModifierType() || typeSrc.IsPointerType())
{
// We cannot vary these.
return false;
}
CType intermediateType;
if ((typeSrc.isInterfaceType() || typeSrc.isDelegateType()) && TryVarianceAdjustmentToGetAccessibleType(semanticChecker, bindingContext, typeSrc.AsAggregateType(), out intermediateType))
{
// If we have an interface or delegate type, then it can potentially be varied by its type arguments
// to produce an accessible type, and if that's the case, then return that.
// Example: IEnumerable<PrivateConcreteFoo> --> IEnumerable<PublicAbstractFoo>
typeDst = intermediateType;
Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup()));
return true;
}
if (typeSrc.IsArrayType() && TryArrayVarianceAdjustmentToGetAccessibleType(semanticChecker, bindingContext, typeSrc.AsArrayType(), out intermediateType))
{
// Similarly to the interface and delegate case, arrays are covariant in their element type and
// so we can potentially produce an array type that is accessible.
// Example: PrivateConcreteFoo[] --> PublicAbstractFoo[]
typeDst = intermediateType;
Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup()));
return true;
}
if (typeSrc.IsNullableType())
{
// We have an inaccessible nullable type, which means that the best we can do is System.ValueType.
typeDst = this.GetOptPredefAgg(PredefinedType.PT_VALUE).getThisType();
Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup()));
return true;
}
if (typeSrc.IsArrayType())
{
// We have an inaccessible array type for which we could not earlier find a better array type
// with a covariant conversion, so the best we can do is System.Array.
typeDst = this.GetReqPredefAgg(PredefinedType.PT_ARRAY).getThisType();
Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup()));
return true;
}
Debug.Assert(typeSrc.IsAggregateType());
if (typeSrc.IsAggregateType())
{
// We have an AggregateType, so recurse on its base class.
AggregateType aggType = typeSrc.AsAggregateType();
AggregateType baseType = aggType.GetBaseClass();
if (baseType == null)
{
// This happens with interfaces, for instance. But in that case, the
// conversion to object does exist, is an implicit reference conversion,
// and so we will use it.
baseType = this.GetReqPredefAgg(PredefinedType.PT_OBJECT).getThisType();
}
return GetBestAccessibleType(semanticChecker, bindingContext, baseType, out typeDst);
}
return false;
}
示例3: SubstEqualTypes
public bool SubstEqualTypes(CType typeDst, CType typeSrc, CType typeCls, TypeArray typeArgsMeth)
{
return SubstEqualTypes(typeDst, typeSrc, typeCls.IsAggregateType() ? typeCls.AsAggregateType().GetTypeArgsAll() : null, typeArgsMeth, SubstTypeFlags.NormNone);
}
示例4: SubstType
public CType SubstType(CType typeSrc, CType typeCls, TypeArray typeArgsMeth)
{
return SubstType(typeSrc, typeCls.IsAggregateType() ? typeCls.AsAggregateType().GetTypeArgsAll() : null, typeArgsMeth);
}
示例5: conversion
/***************************************************************************************************
Determine whether there is an explicit or implicit reference conversion (or identity conversion)
from typeSrc to typeDst. This is when:
13.2.3 Explicit reference conversions
The explicit reference conversions are:
* From object to any reference-type.
* From any class-type S to any class-type T, provided S is a base class of T.
* From any class-type S to any interface-type T, provided S is not sealed and provided S does not implement T.
* From any interface-type S to any class-type T, provided T is not sealed or provided T implements S.
* From any interface-type S to any interface-type T, provided S is not derived from T.
* From an array-type S with an element type SE to an array-type T with an element type TE, provided all of the following are true:
o S and T differ only in element type. (In other words, S and T have the same number of dimensions.)
o An explicit reference conversion exists from SE to TE.
* From System.Array and the interfaces it implements, to any array-type.
* From System.Delegate and the interfaces it implements, to any delegate-type.
* From a one-dimensional array-type S[] to System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces, provided there is an explicit reference conversion from S to T.
* From a generic delegate type S to generic delegate type T, provided all of the follow are true:
o Both types are constructed generic types of the same generic delegate type, D<X1,... Xk>.That is,
S is D<S1,... Sk> and T is D<T1,... Tk>.
o S is not compatible with or identical to T.
o If type parameter Xi is declared to be invariant then Si must be identical to Ti.
o If type parameter Xi is declared to be covariant ("out") then Si must be convertible
to Ti via an identify conversion, implicit reference conversion, or explicit reference conversion.
o If type parameter Xi is declared to be contravariant ("in") then either Si must be identical to Ti,
or Si and Ti must both be reference types.
* From System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces to a one-dimensional array-type S[], provided there is an implicit or explicit reference conversion from S[] to System.Collections.Generic.IList<T> or System.Collections.Generic.IReadOnlyList<T>. This is precisely when either S and T are the same type or there is an implicit or explicit reference conversion from S to T.
For a type-parameter T that is known to be a reference type (§25.7), the following explicit reference conversions exist:
* From the effective base class C of T to T and from any base class of C to T.
* From any interface-type to T.
* From T to any interface-type I provided there isn’t already an implicit reference conversion from T to I.
* From a type-parameter U to T provided that T depends on U (§25.7). [Note: Since T is known to be a reference type, within the scope of T, the run-time type of U will always be a reference type, even if U is not known to be a reference type at compile-time. end note]
* Both src and dst are reference types and there is a builtin explicit conversion from
src to dst.
* Or src is a reference type and dst is a base type of src (in which case the conversion is
implicit as well).
* Or dst is a reference type and src is a base type of dst.
The latter two cases can happen with type variables even though the other type variable is not
a reference type.
***************************************************************************************************/
public static bool FExpRefConv(SymbolLoader loader, CType typeSrc, CType typeDst)
{
Debug.Assert(typeSrc != null);
Debug.Assert(typeDst != null);
if (typeSrc.IsRefType() && typeDst.IsRefType())
{
// is there an implicit reference conversion in either direction?
// this handles the bulk of the cases ...
if (loader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst) ||
loader.HasIdentityOrImplicitReferenceConversion(typeDst, typeSrc))
{
return true;
}
// For a type-parameter T that is known to be a reference type (§25.7), the following explicit reference conversions exist:
// • From any interface-type to T.
// • From T to any interface-type I provided there isn’t already an implicit reference conversion from T to I.
if (typeSrc.isInterfaceType() && typeDst.IsTypeParameterType())
{
return true;
}
if (typeSrc.IsTypeParameterType() && typeDst.isInterfaceType())
{
return true;
}
// * From any class-type S to any interface-type T, provided S is not sealed
// * From any interface-type S to any class-type T, provided T is not sealed
// * From any interface-type S to any interface-type T, provided S is not derived from T.
if (typeSrc.IsAggregateType() && typeDst.IsAggregateType())
{
AggregateSymbol aggSrc = typeSrc.AsAggregateType().getAggregate();
AggregateSymbol aggDest = typeDst.AsAggregateType().getAggregate();
if ((aggSrc.IsClass() && !aggSrc.IsSealed() && aggDest.IsInterface()) ||
(aggSrc.IsInterface() && aggDest.IsClass() && !aggDest.IsSealed()) ||
(aggSrc.IsInterface() && aggDest.IsInterface()))
{
return true;
}
}
// * From an array-type S with an element type SE to an array-type T with an element type TE, provided all of the following are true:
// o S and T differ only in element type. (In other words, S and T have the same number of dimensions.)
// o An explicit reference conversion exists from SE to TE.
if (typeSrc.IsArrayType() && typeDst.IsArrayType())
{
return typeSrc.AsArrayType().rank == typeDst.AsArrayType().rank && FExpRefConv(loader, typeSrc.AsArrayType().GetElementType(), typeDst.AsArrayType().GetElementType());
}
// * From a one-dimensional array-type S[] to System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T>
// and their base interfaces, provided there is an explicit reference conversion from S to T.
if (typeSrc.IsArrayType())
{
if (typeSrc.AsArrayType().rank != 1 ||
!typeDst.isInterfaceType() || typeDst.AsAggregateType().GetTypeArgsAll().Size != 1)
//.........这里部分代码省略.........
示例6: ErrAppendParentType
protected void ErrAppendParentType(CType pType, SubstContext pctx)
{
if (pType.IsErrorType())
{
if (pType.AsErrorType().HasTypeParent())
{
ErrAppendType(pType.AsErrorType().GetTypeParent(), null);
ErrAppendChar('.');
}
else
{
ErrAppendParentCore(pType.AsErrorType().GetNSParent(), pctx);
}
}
else if (pType.IsAggregateType())
{
ErrAppendParentCore(pType.AsAggregateType().GetOwningAggregate(), pctx);
}
else if (pType.GetBaseOrParameterOrElementType() != null)
{
ErrAppendType(pType.GetBaseOrParameterOrElementType(), null);
ErrAppendChar('.');
}
}
示例7: UpperBoundConstructedInference
////////////////////////////////////////////////////////////////////////////////
private bool UpperBoundConstructedInference(CType pSource, CType pDest)
{
if (!pSource.IsAggregateType())
{
return false;
}
AggregateType pConstructedSource = pSource.AsAggregateType();
TypeArray pSourceArgs = pConstructedSource.GetTypeArgsAll();
if (pSourceArgs.size == 0)
{
return false;
}
// SPEC: Otherwise, if V is a constructed CType C<V1...Vk> and U is
// SPEC: C<U1...Uk> then an exact inference,
// SPEC: lower bound inference or upper bound inference
// SPEC: is made from each Ui to the corresponding Vi.
if (pDest.IsAggregateType() &&
pConstructedSource.GetOwningAggregate() == pDest.AsAggregateType().GetOwningAggregate())
{
if (pDest.isInterfaceType() || pDest.isDelegateType())
{
UpperBoundTypeArgumentInference(pConstructedSource, pDest.AsAggregateType());
}
else
{
ExactTypeArgumentInference(pConstructedSource, pDest.AsAggregateType());
}
return true;
}
// SPEC: Otherwise, if U is a class CType C<U1...Uk> and V is a class CType which
// SPEC: inherits directly or indirectly from C<V1...Vk> then an exact ...
if (UpperBoundClassInference(pConstructedSource, pDest))
{
return true;
}
// SPEC: Otherwise, if U is an interface CType C<U1...Uk> and V is a class CType
// SPEC: or struct CType and there is a unique set V1...Vk such that V directly
// SPEC: or indirectly implements C<V1...Vk> then an exact ...
// SPEC: ... and U is an interface CType ...
if (UpperBoundInterfaceInference(pConstructedSource, pDest))
{
return true;
}
return false;
}
示例8: RemapToOverride
////////////////////////////////////////////////////////////////////////////////
// For a base call we need to remap from the virtual to the specific override
// to invoke. This is also used to map a virtual on pObject (like ToString) to
// the specific override when the pObject is a simple type (int, bool, char,
// etc). In these cases it is safe to assume that any override won't later be
// removed.... We start searching from "typeObj" up the superclass hierarchy
// until we find a method with an exact signature match.
public static void RemapToOverride(SymbolLoader symbolLoader, SymWithType pswt, CType typeObj)
{
// For a property/indexer we remap the accessors, not the property/indexer.
// Since every event has both accessors we remap the event instead of the accessors.
Debug.Assert(pswt && (pswt.Sym.IsMethodSymbol() || pswt.Sym.IsEventSymbol() || pswt.Sym.IsMethodOrPropertySymbol()));
Debug.Assert(typeObj != null);
// Don't remap static or interface methods.
if (typeObj.IsNullableType())
{
typeObj = typeObj.AsNullableType().GetAts(symbolLoader.GetErrorContext());
if (typeObj == null)
{
VSFAIL("Why did GetAts return null?");
return;
}
}
// Don't remap non-virtual members
if (!typeObj.IsAggregateType() || typeObj.isInterfaceType() || !pswt.Sym.IsVirtual())
{
return;
}
symbmask_t mask = pswt.Sym.mask();
AggregateType atsObj = typeObj.AsAggregateType();
// Search for an override version of the method.
while (atsObj != null && atsObj.getAggregate() != pswt.Sym.parent)
{
for (Symbol symT = symbolLoader.LookupAggMember(pswt.Sym.name, atsObj.getAggregate(), mask);
symT != null;
symT = symbolLoader.LookupNextSym(symT, atsObj.getAggregate(), mask))
{
if (symT.IsOverride() && (symT.SymBaseVirtual() == pswt.Sym || symT.SymBaseVirtual() == pswt.Sym.SymBaseVirtual()))
{
pswt.Set(symT, atsObj);
return;
}
}
atsObj = atsObj.GetBaseClass();
}
}
示例9: CheckConstraints
// Check the constraints of any type arguments in the given Type.
public static bool CheckConstraints(CSemanticChecker checker, ErrorHandling errHandling, CType type, CheckConstraintsFlags flags)
{
type = type.GetNakedType(false);
if (type.IsNullableType())
{
CType typeT = type.AsNullableType().GetAts(checker.GetErrorContext());
if (typeT != null)
type = typeT;
else
type = type.GetNakedType(true);
}
if (!type.IsAggregateType())
return true;
AggregateType ats = type.AsAggregateType();
if (ats.GetTypeArgsAll().size == 0)
{
// Common case: there are no type vars, so there are no constraints.
ats.fConstraintsChecked = true;
ats.fConstraintError = false;
return true;
}
if (ats.fConstraintsChecked)
{
// Already checked.
if (!ats.fConstraintError || (flags & CheckConstraintsFlags.NoDupErrors) != 0)
{
// No errors or no need to report errors again.
return !ats.fConstraintError;
}
}
TypeArray typeVars = ats.getAggregate().GetTypeVars();
TypeArray typeArgsThis = ats.GetTypeArgsThis();
TypeArray typeArgsAll = ats.GetTypeArgsAll();
Debug.Assert(typeVars.size == typeArgsThis.size);
if (!ats.fConstraintsChecked)
{
ats.fConstraintsChecked = true;
ats.fConstraintError = false;
}
// Check the outer type first. If CheckConstraintsFlags.Outer is not specified and the
// outer type has already been checked then don't bother checking it.
if (ats.outerType != null && ((flags & CheckConstraintsFlags.Outer) != 0 || !ats.outerType.fConstraintsChecked))
{
CheckConstraints(checker, errHandling, ats.outerType, flags);
ats.fConstraintError |= ats.outerType.fConstraintError;
}
if (typeVars.size > 0)
ats.fConstraintError |= !CheckConstraintsCore(checker, errHandling, ats.getAggregate(), typeVars, typeArgsThis, typeArgsAll, null, (flags & CheckConstraintsFlags.NoErrors));
// Now check type args themselves.
for (int i = 0; i < typeArgsThis.size; i++)
{
CType arg = typeArgsThis.Item(i).GetNakedType(true);
if (arg.IsAggregateType() && !arg.AsAggregateType().fConstraintsChecked)
{
CheckConstraints(checker, errHandling, arg.AsAggregateType(), flags | CheckConstraintsFlags.Outer);
if (arg.AsAggregateType().fConstraintError)
ats.fConstraintError = true;
}
}
return !ats.fConstraintError;
}
示例10: HasAnyBaseInterfaceConversion
private bool HasAnyBaseInterfaceConversion(CType pDerived, CType pBase)
{
if (!pBase.isInterfaceType())
{
return false;
}
if (!pDerived.IsAggregateType())
{
return false;
}
AggregateType atsDer = pDerived.AsAggregateType();
while (atsDer != null)
{
TypeArray ifacesAll = atsDer.GetIfacesAll();
for (int i = 0; i < ifacesAll.size; i++)
{
if (HasInterfaceConversion(ifacesAll.Item(i).AsAggregateType(), pBase.AsAggregateType()))
{
return true;
}
}
atsDer = atsDer.GetBaseClass();
}
return false;
}
示例11: HasBaseConversion
public bool HasBaseConversion(CType pSource, CType pDest)
{
// By a "base conversion" we mean:
//
// * an identity conversion
// * an implicit reference conversion
// * an implicit boxing conversion
// * an implicit type parameter conversion
//
// In other words, these are conversions that can be made to a base
// class, base interface or co/contravariant type without any change in
// representation other than boxing. A conversion from, say, int to double,
// is NOT a "base conversion", because representation is changed. A conversion
// from, say, lambda to expression tree is not a "base conversion" because
// do not have a type.
//
// The existence of a base conversion depends solely upon the source and
// destination types, not the source expression.
//
// This notion is not found in the spec but it is useful in the implementation.
if (pSource.IsAggregateType() && pDest.isPredefType(PredefinedType.PT_OBJECT))
{
// If we are going from any aggregate type (class, struct, interface, enum or delegate)
// to object, we immediately return true. This may seem like a mere optimization --
// after all, if we have an aggregate then we have some kind of implicit conversion
// to object.
//
// However, it is not a mere optimization; this introduces a control flow change
// in error reporting scenarios for unresolved type forwarders. If a type forwarder
// cannot be resolved then the resulting type symbol will be an aggregate, but
// we will not be able to classify it into class, struct, etc.
//
// We know that we will have an error in this case; we do not wish to compound
// that error by giving a spurious "you cannot convert this thing to object"
// error, which, after all, will go away when the type forwarding problem is
// fixed.
return true;
}
if (HasIdentityOrImplicitReferenceConversion(pSource, pDest))
{
return true;
}
if (HasImplicitBoxingConversion(pSource, pDest))
{
return true;
}
if (pSource.IsTypeParameterType() &&
HasImplicitTypeParameterBaseConversion(pSource.AsTypeParameterType(), pDest))
{
return true;
}
return false;
}
示例12: IsBaseClass
public bool IsBaseClass(CType pDerived, CType pBase)
{
Debug.Assert(pDerived != null);
Debug.Assert(pBase != null);
// A base class has got to be a class. The derived type might be a struct.
if (!pBase.isClassType())
{
return false;
}
if (pDerived.IsNullableType())
{
pDerived = pDerived.AsNullableType().GetAts(ErrorContext);
if (pDerived == null)
{
return false;
}
}
if (!pDerived.IsAggregateType())
{
return false;
}
AggregateType atsDer = pDerived.AsAggregateType();
AggregateType atsBase = pBase.AsAggregateType();
AggregateType atsCur = atsDer.GetBaseClass();
while (atsCur != null)
{
if (atsCur == atsBase)
{
return true;
}
atsCur = atsCur.GetBaseClass();
}
return false;
}
示例13: IsBaseInterface
public bool IsBaseInterface(CType pDerived, CType pBase)
{
Debug.Assert(pDerived != null);
Debug.Assert(pBase != null);
if (!pBase.isInterfaceType())
{
return false;
}
if (!pDerived.IsAggregateType())
{
return false;
}
AggregateType atsDer = pDerived.AsAggregateType();
while (atsDer != null)
{
TypeArray ifacesAll = atsDer.GetIfacesAll();
for (int i = 0; i < ifacesAll.Size; i++)
{
if (AreTypesEqualForConversion(ifacesAll.Item(i), pBase))
{
return true;
}
}
atsDer = atsDer.GetBaseClass();
}
return false;
}
示例14: GetAggTypeSym
// It would be nice to make this a virtual method on typeSym.
public AggregateType GetAggTypeSym(CType typeSym)
{
Debug.Assert(typeSym != null);
Debug.Assert(typeSym.IsAggregateType() ||
typeSym.IsTypeParameterType() ||
typeSym.IsArrayType() ||
typeSym.IsNullableType());
switch (typeSym.GetTypeKind())
{
case TypeKind.TK_AggregateType:
return typeSym.AsAggregateType();
case TypeKind.TK_ArrayType:
return GetReqPredefType(PredefinedType.PT_ARRAY);
case TypeKind.TK_TypeParameterType:
return typeSym.AsTypeParameterType().GetEffectiveBaseClass();
case TypeKind.TK_NullableType:
return typeSym.AsNullableType().GetAts(ErrorContext);
}
Debug.Assert(false, "Bad typeSym!");
return null;
}
示例15: ExactConstructedInference
////////////////////////////////////////////////////////////////////////////////
private bool ExactConstructedInference(CType pSource, CType pDest)
{
// SPEC: Otherwise, if V is a constructed CType C<V1...Vk> and U is a constructed
// SPEC: CType C<U1...Uk> then an exact inference
// SPEC: is made from each Ui to the corresponding Vi.
if (!pSource.IsAggregateType() || !pDest.IsAggregateType())
{
return false;
}
AggregateType pConstructedSource = pSource.AsAggregateType();
AggregateType pConstructedDest = pDest.AsAggregateType();
if (pConstructedSource.GetOwningAggregate() != pConstructedDest.GetOwningAggregate())
{
return false;
}
ExactTypeArgumentInference(pConstructedSource, pConstructedDest);
return true;
}