本文整理汇总了C#中Microsoft.CSharp.RuntimeBinder.Semantics.CType.IsTypeParameterType方法的典型用法代码示例。如果您正苦于以下问题:C# CType.IsTypeParameterType方法的具体用法?C# CType.IsTypeParameterType怎么用?C# CType.IsTypeParameterType使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Microsoft.CSharp.RuntimeBinder.Semantics.CType
的用法示例。
在下文中一共展示了CType.IsTypeParameterType方法的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: CheckAccessCore
//
// SymbolLoader forwarders (end)
/////////////////////////////////////////////////////////////////////////////////
//
// Utility methods
//
protected ACCESSERROR CheckAccessCore(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());
switch (symCheck.GetAccess())
{
default:
throw Error.InternalCompilerError();
//return ACCESSERROR.ACCESSERROR_NOACCESS;
case ACCESS.ACC_UNKNOWN:
return ACCESSERROR.ACCESSERROR_NOACCESS;
case ACCESS.ACC_PUBLIC:
return ACCESSERROR.ACCESSERROR_NOERROR;
case ACCESS.ACC_PRIVATE:
case ACCESS.ACC_PROTECTED:
if (symWhere == null)
{
return ACCESSERROR.ACCESSERROR_NOACCESS;
}
break;
case ACCESS.ACC_INTERNAL:
case ACCESS.ACC_INTERNALPROTECTED: // Check internal, then protected.
if (symWhere == null)
{
return ACCESSERROR.ACCESSERROR_NOACCESS;
}
if (symWhere.SameAssemOrFriend(symCheck))
{
return ACCESSERROR.ACCESSERROR_NOERROR;
}
if (symCheck.GetAccess() == ACCESS.ACC_INTERNAL)
{
return ACCESSERROR.ACCESSERROR_NOACCESS;
}
break;
}
// Should always have atsCheck for private and protected access check.
// We currently don't need it since access doesn't respect instantiation.
// We just use symWhere.parent.AsAggregateSymbol() instead.
AggregateSymbol aggCheck = symCheck.parent.AsAggregateSymbol();
// Find the inner-most enclosing AggregateSymbol.
AggregateSymbol aggWhere = null;
for (Symbol symT = symWhere; symT != null; symT = symT.parent)
{
if (symT.IsAggregateSymbol())
{
aggWhere = symT.AsAggregateSymbol();
break;
}
if (symT.IsAggregateDeclaration())
{
aggWhere = symT.AsAggregateDeclaration().Agg();
break;
}
}
if (aggWhere == null)
{
return ACCESSERROR.ACCESSERROR_NOACCESS;
}
// First check for private access.
for (AggregateSymbol agg = aggWhere; agg != null; agg = agg.GetOuterAgg())
{
if (agg == aggCheck)
{
return ACCESSERROR.ACCESSERROR_NOERROR;
}
}
if (symCheck.GetAccess() == ACCESS.ACC_PRIVATE)
{
return ACCESSERROR.ACCESSERROR_NOACCESS;
}
// Handle the protected case - which is the only real complicated one.
Debug.Assert(symCheck.GetAccess() == ACCESS.ACC_PROTECTED || symCheck.GetAccess() == ACCESS.ACC_INTERNALPROTECTED);
//.........这里部分代码省略.........
示例3: UpperBoundTypeParameterInference
////////////////////////////////////////////////////////////////////////////////
private bool UpperBoundTypeParameterInference(CType pSource, CType pDest)
{
// SPEC: If V is one of the unfixed Xi then U is added to the set of upper bounds
// SPEC: for Xi.
if (pDest.IsTypeParameterType())
{
TypeParameterType pTPType = pDest.AsTypeParameterType();
if (pTPType.IsMethodTypeParameter() && IsUnfixed(pTPType))
{
AddUpperBound(pTPType, pSource);
return true;
}
}
return false;
}
示例4: LowerBoundInterfaceInference
////////////////////////////////////////////////////////////////////////////////
private bool LowerBoundInterfaceInference(CType pSource, AggregateType pDest)
{
if (!pDest.isInterfaceType())
{
return false;
}
// SPEC: Otherwise, if V is an interface CType C<V1...Vk> and U is a class CType
// SPEC: or struct CType and there is a unique set U1...Uk such that U directly
// SPEC: or indirectly implements C<U1...Uk> then an
// SPEC: exact, upper-bound, or lower-bound inference ...
// SPEC: ... and U is an interface CType ...
// SPEC: ... and U is a CType parameter ...
//TypeArray pInterfaces = null;
if (!pSource.isStructType() && !pSource.isClassType() &&
!pSource.isInterfaceType() && !pSource.IsTypeParameterType())
{
return false;
}
var interfaces = pSource.AllPossibleInterfaces();
AggregateType pInterface = null;
foreach (AggregateType pCurrent in interfaces)
{
if (pCurrent.GetOwningAggregate() == pDest.GetOwningAggregate())
{
if (pInterface == null)
{
pInterface = pCurrent;
}
else if (pInterface != pCurrent)
{
// Not unique. Bail out.
return false;
}
}
}
if (pInterface == null)
{
return false;
}
LowerBoundTypeArgumentInference(pInterface, pDest);
return true;
}
示例5: LowerBoundClassInference
////////////////////////////////////////////////////////////////////////////////
private bool LowerBoundClassInference(CType pSource, AggregateType pDest)
{
if (!pDest.isClassType())
{
return false;
}
// SPEC: Otherwise, if V is a class CType C<V1...Vk> and U is a class CType which
// SPEC: inherits directly or indirectly from C<U1...Uk>
// SPEC: then an exact inference is made from each Ui to the corresponding Vi.
// SPEC: Otherwise, if V is a class CType C<V1...Vk> and U is a CType parameter
// SPEC: with effective base class C<U1...Uk>
// SPEC: then an exact inference is made from each Ui to the corresponding Vi.
// SPEC: Otherwise, if V is a class CType C<V1...Vk> and U is a CType parameter
// SPEC: with an effective base class which inherits directly or indirectly from
// SPEC: C<U1...Uk> then an exact inference is made
// SPEC: from each Ui to the corresponding Vi.
AggregateType pSourceBase = null;
if (pSource.isClassType())
{
pSourceBase = pSource.AsAggregateType().GetBaseClass();
}
else if (pSource.IsTypeParameterType())
{
pSourceBase = pSource.AsTypeParameterType().GetEffectiveBaseClass();
}
while (pSourceBase != null)
{
if (pSourceBase.GetOwningAggregate() == pDest.GetOwningAggregate())
{
ExactTypeArgumentInference(pSourceBase, pDest);
return true;
}
pSourceBase = pSourceBase.GetBaseClass();
}
return false;
}
示例6: LowerBoundArrayInference
////////////////////////////////////////////////////////////////////////////////
private bool LowerBoundArrayInference(CType pSource, CType pDest)
{
// SPEC: Otherwise, if U is an array CType Ue[...] and V is either an array
// SPEC: CType Ve[...] of the same rank, or if U is a one-dimensional array
// SPEC: CType Ue[] and V is one of IEnumerable<Ve>, ICollection<Ve>,
// SPEC: IList<Ve>, IReadOnlyCollection<Ve> or IReadOnlyList<Ve> then
// SPEC: if Ue is known to be a reference CType then a lower-bound inference
// SPEC: from Ue to Ve is made.
// SPEC: otherwise an exact inference from Ue to Ve is made.
// Consider the following:
//
// abstract class B<T> { public abstract M<U>(U u) : where U : T; }
// class D : B<int[]> {
// static void M<X>(X[] x) { }
// public override M<U>(U u) { M(u); } // should infer M<int>
// }
if (pSource.IsTypeParameterType())
{
pSource = pSource.AsTypeParameterType().GetEffectiveBaseClass();
}
if (!pSource.IsArrayType())
{
return false;
}
ArrayType pArraySource = pSource.AsArrayType();
CType pElementSource = pArraySource.GetElementType();
CType pElementDest = null;
if (pDest.IsArrayType())
{
ArrayType pArrayDest = pDest.AsArrayType();
if (pArrayDest.rank != pArraySource.rank)
{
return false;
}
pElementDest = pArrayDest.GetElementType();
}
else if (pDest.isPredefType(PredefinedType.PT_G_IENUMERABLE) ||
pDest.isPredefType(PredefinedType.PT_G_ICOLLECTION) ||
pDest.isPredefType(PredefinedType.PT_G_ILIST) ||
pDest.isPredefType(PredefinedType.PT_G_IREADONLYCOLLECTION) ||
pDest.isPredefType(PredefinedType.PT_G_IREADONLYLIST))
{
if (pArraySource.rank != 1)
{
return false;
}
AggregateType pAggregateDest = pDest.AsAggregateType();
pElementDest = pAggregateDest.GetTypeArgsThis().Item(0);
}
else
{
return false;
}
if (pElementSource.IsRefType())
{
LowerBoundInference(pElementSource, pElementDest);
}
else
{
ExactInference(pElementSource, pElementDest);
}
return true;
}
示例7: 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;
}
示例8: 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;
}
示例9: SatisfiesBound
////////////////////////////////////////////////////////////////////////////////
// Determine whether the arg type satisfies the typeBnd constraint. Note that
// typeBnd could be just about any type (since we added naked type parameter
// constraints).
private static bool SatisfiesBound(CSemanticChecker checker, CType arg, CType typeBnd)
{
if (typeBnd == arg)
return true;
switch (typeBnd.GetTypeKind())
{
default:
Debug.Assert(false, "Unexpected type.");
return false;
case TypeKind.TK_VoidType:
case TypeKind.TK_PointerType:
case TypeKind.TK_ErrorType:
return false;
case TypeKind.TK_ArrayType:
case TypeKind.TK_TypeParameterType:
break;
case TypeKind.TK_NullableType:
typeBnd = typeBnd.AsNullableType().GetAts(checker.GetErrorContext());
if (null == typeBnd)
return true;
break;
case TypeKind.TK_AggregateType:
break;
}
Debug.Assert(typeBnd.IsAggregateType() || typeBnd.IsTypeParameterType() || typeBnd.IsArrayType());
switch (arg.GetTypeKind())
{
default:
return false;
case TypeKind.TK_ErrorType:
case TypeKind.TK_PointerType:
return false;
case TypeKind.TK_NullableType:
arg = arg.AsNullableType().GetAts(checker.GetErrorContext());
if (null == arg)
return true;
// Fall through.
goto case TypeKind.TK_TypeParameterType;
case TypeKind.TK_TypeParameterType:
case TypeKind.TK_ArrayType:
case TypeKind.TK_AggregateType:
return checker.GetSymbolLoader().HasBaseConversion(arg, typeBnd);
}
}
示例10: CheckSingleConstraint
private static bool CheckSingleConstraint(CSemanticChecker checker, ErrorHandling errHandling, Symbol symErr, TypeParameterType var, CType arg, TypeArray typeArgsCls, TypeArray typeArgsMeth, CheckConstraintsFlags flags)
{
bool fReportErrors = 0 == (flags & CheckConstraintsFlags.NoErrors);
if (arg.IsOpenTypePlaceholderType())
{
return true;
}
if (arg.IsErrorType())
{
// Error should have been reported previously.
return false;
}
if (checker.CheckBogus(arg))
{
if (fReportErrors)
{
errHandling.ErrorRef(ErrorCode.ERR_BogusType, arg);
}
return false;
}
if (arg.IsPointerType() || arg.isSpecialByRefType())
{
if (fReportErrors)
{
errHandling.Error(ErrorCode.ERR_BadTypeArgument, arg);
}
return false;
}
if (arg.isStaticClass())
{
if (fReportErrors)
{
checker.ReportStaticClassError(null, arg, ErrorCode.ERR_GenericArgIsStaticClass);
}
return false;
}
bool fError = false;
if (var.HasRefConstraint() && !arg.IsRefType())
{
if (fReportErrors)
{
errHandling.ErrorRef(ErrorCode.ERR_RefConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg);
}
fError = true;
}
TypeArray bnds = checker.GetSymbolLoader().GetTypeManager().SubstTypeArray(var.GetBounds(), typeArgsCls, typeArgsMeth);
int itypeMin = 0;
if (var.HasValConstraint())
{
// If we have a type variable that is constrained to a value type, then we
// want to check if its a nullable type, so that we can report the
// constraint error below. In order to do this however, we need to check
// that either the type arg is not a value type, or it is a nullable type.
//
// To check whether or not its a nullable type, we need to get the resolved
// bound from the type argument and check against that.
bool bIsValueType = arg.IsValType();
bool bIsNullable = arg.IsNullableType();
if (bIsValueType && arg.IsTypeParameterType())
{
TypeArray pArgBnds = arg.AsTypeParameterType().GetBounds();
if (pArgBnds.size > 0)
{
bIsNullable = pArgBnds.Item(0).IsNullableType();
}
}
if (!bIsValueType || bIsNullable)
{
if (fReportErrors)
{
errHandling.ErrorRef(ErrorCode.ERR_ValConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg);
}
fError = true;
}
// Since FValCon() is set it is redundant to check System.ValueType as well.
if (bnds.size != 0 && bnds.Item(0).isPredefType(PredefinedType.PT_VALUE))
{
itypeMin = 1;
}
}
for (int j = itypeMin; j < bnds.size; j++)
{
CType typeBnd = bnds.Item(j);
//.........这里部分代码省略.........
示例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: HasImplicitBoxingConversion
public bool HasImplicitBoxingConversion(CType pSource, CType pDest)
{
Debug.Assert(pSource != null);
Debug.Assert(pDest != null);
// Certain type parameter conversions are classified as boxing conversions.
if (pSource.IsTypeParameterType() &&
HasImplicitBoxingTypeParameterConversion(pSource.AsTypeParameterType(), pDest))
{
return true;
}
// The rest of the boxing conversions only operate when going from a value type
// to a reference type.
if (!pSource.IsValType() || !pDest.IsRefType())
{
return false;
}
// A boxing conversion exists from a nullable type to a reference type
// if and only if a boxing conversion exists from the underlying type.
if (pSource.IsNullableType())
{
return HasImplicitBoxingConversion(pSource.AsNullableType().GetUnderlyingType(), pDest);
}
// A boxing conversion exists from any non-nullable value type to object,
// to System.ValueType, and to any interface type implemented by the
// non-nullable value type. Furthermore, an enum type can be converted
// to the type System.Enum.
// We set the base class of the structs to System.ValueType, System.Enum, etc,
// so we can just check here.
if (IsBaseClass(pSource, pDest))
{
return true;
}
if (HasAnyBaseInterfaceConversion(pSource, pDest))
{
return true;
}
return false;
}
示例13: HasImplicitTypeParameterBaseConversion
private bool HasImplicitTypeParameterBaseConversion(
TypeParameterType pSource, CType pDest)
{
Debug.Assert(pSource != null);
Debug.Assert(pDest != null);
if (HasImplicitReferenceTypeParameterConversion(pSource, pDest))
{
return true;
}
if (HasImplicitBoxingTypeParameterConversion(pSource, pDest))
{
return true;
}
if (pDest.IsTypeParameterType() && pSource.DependsOn(pDest.AsTypeParameterType()))
{
return true;
}
return false;
}
示例14: HasImplicitReferenceTypeParameterConversion
private bool HasImplicitReferenceTypeParameterConversion(
TypeParameterType pSource, CType pDest)
{
Debug.Assert(pSource != null);
Debug.Assert(pDest != null);
if (!pSource.IsRefType())
{
// Not a reference conversion.
return false;
}
// The following implicit conversions exist for a given type parameter T:
//
// * From T to its effective base class C.
AggregateType pEBC = pSource.GetEffectiveBaseClass();
if (pDest == pEBC)
{
return true;
}
// * From T to any base class of C.
if (IsBaseClass(pEBC, pDest))
{
return true;
}
// * From T to any interface implemented by C.
if (IsBaseInterface(pEBC, pDest))
{
return true;
}
// * From T to any interface type I in T's effective interface set, and
// from T to any base interface of I.
TypeArray pInterfaces = pSource.GetInterfaceBounds();
for (int i = 0; i < pInterfaces.Size; ++i)
{
if (pInterfaces.Item(i) == pDest)
{
return true;
}
}
// * From T to a type parameter U, provided T depends on U.
if (pDest.IsTypeParameterType() && pSource.DependsOn(pDest.AsTypeParameterType()))
{
return true;
}
return false;
}
示例15: HasImplicitReferenceConversion
//.........这里部分代码省略.........
// }
// VARIANCE EXTENSIONS:
// * From any class type S to any interface type T provided S implements an interface
// convertible to T.
// * From any interface type S to any interface type T provided S implements an interface
// convertible to T.
// * From any interface type S to any interface type T provided S is not T and S is
// an interface convertible to T.
if (pSource.isClassType() && pDest.isInterfaceType() && HasAnyBaseInterfaceConversion(pSource, pDest))
{
return true;
}
if (pSource.isInterfaceType() && pDest.isInterfaceType() && HasAnyBaseInterfaceConversion(pSource, pDest))
{
return true;
}
if (pSource.isInterfaceType() && pDest.isInterfaceType() && pSource != pDest &&
HasInterfaceConversion(pSource.AsAggregateType(), pDest.AsAggregateType()))
{
return true;
}
// * From an array type S with an element type SE to an array type T with element type TE
// provided that all of the following are true:
// * S and T differ only in element type. In other words, S and T have the same number of dimensions.
// * Both SE and TE are reference types.
// * An implicit reference conversion exists from SE to TE.
if (pSource.IsArrayType() && pDest.IsArrayType() &&
HasCovariantArrayConversion(pSource.AsArrayType(), pDest.AsArrayType()))
{
return true;
}
// * From any array type to System.Array or any interface implemented by System.Array.
if (pSource.IsArrayType() && (pDest.isPredefType(PredefinedType.PT_ARRAY) ||
IsBaseInterface(GetReqPredefType(PredefinedType.PT_ARRAY, false), pDest)))
{
return true;
}
// * From a single-dimensional array type S[] to IList<T> and its base
// interfaces, provided that there is an implicit identity or reference
// conversion from S to T.
if (pSource.IsArrayType() && HasArrayConversionToInterface(pSource.AsArrayType(), pDest))
{
return true;
}
// * From any delegate type to System.Delegate
//
// SPEC OMISSION:
//
// The spec should actually say
//
// * From any delegate type to System.Delegate
// * From any delegate type to System.MulticastDelegate
// * From any delegate type to any interface implemented by System.MulticastDelegate
if (pSource.isDelegateType() &&
(pDest.isPredefType(PredefinedType.PT_MULTIDEL) ||
pDest.isPredefType(PredefinedType.PT_DELEGATE) ||
IsBaseInterface(GetReqPredefType(PredefinedType.PT_MULTIDEL, false), pDest)))
{
return true;
}
// VARIANCE EXTENSION:
// * From any delegate type S to a delegate type T provided S is not T and
// S is a delegate convertible to T
if (pSource.isDelegateType() && pDest.isDelegateType() &&
HasDelegateConversion(pSource.AsAggregateType(), pDest.AsAggregateType()))
{
return true;
}
// * From the null literal to any reference type
// NOTE: We extend the specification here. The C# 3.0 spec does not describe
// a "null type". Rather, it says that the null literal is typeless, and is
// convertible to any reference or nullable type. However, the C# 2.0 and 3.0
// implementations have a "null type" which some expressions other than the
// null literal may have. (For example, (null??null), which is also an
// extension to the specification.)
if (pSource.IsNullType() && pDest.IsRefType())
{
return true;
}
if (pSource.IsNullType() && pDest.IsNullableType())
{
return true;
}
// * Implicit conversions involving type parameters that are known to be reference types.
if (pSource.IsTypeParameterType() &&
HasImplicitReferenceTypeParameterConversion(pSource.AsTypeParameterType(), pDest))
{
return true;
}
return false;
}