diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs
index 9d4b360635..7e0a89d8f8 100644
--- a/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs
+++ b/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs
@@ -107,7 +107,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
///
/// Gets the effective interface set of this type parameter.
///
- IList EffectiveInterfaceSet { get; }
+ ICollection EffectiveInterfaceSet { get; }
///
/// Gets if the type parameter has the 'new()' constraint.
diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs
index 8b12e0e920..cede6c7a8b 100644
--- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs
+++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs
@@ -94,48 +94,73 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IType EffectiveBaseClass {
get {
- if (effectiveBaseClass == null)
- effectiveBaseClass = CalculateEffectiveBaseClass();
+ if (effectiveBaseClass == null) {
+ // protect against cyclic type parameters
+ using (var busyLock = BusyManager.Enter(this)) {
+ if (!busyLock.Success)
+ return SpecialType.UnknownType; // don't cache this error
+ effectiveBaseClass = CalculateEffectiveBaseClass();
+ }
+ }
return effectiveBaseClass;
}
}
IType CalculateEffectiveBaseClass()
{
- // protect against cyclic type parameters
- using (var busyLock = BusyManager.Enter(this)) {
- if (!busyLock.Success)
- return SpecialType.UnknownType;
-
- if (HasValueTypeConstraint)
- return this.Compilation.FindType(KnownTypeCode.ValueType);
-
- List classTypeConstraints = new List();
- foreach (IType constraint in this.DirectBaseTypes) {
- if (constraint.Kind == TypeKind.Class) {
- classTypeConstraints.Add(constraint);
- } else if (constraint.Kind == TypeKind.TypeParameter) {
- IType baseClass = ((ITypeParameter)constraint).EffectiveBaseClass;
- if (baseClass.Kind == TypeKind.Class)
- classTypeConstraints.Add(baseClass);
- }
- }
- if (classTypeConstraints.Count == 0)
- return this.Compilation.FindType(KnownTypeCode.Object);
- // Find the derived-most type in the resulting set:
- IType result = classTypeConstraints[0];
- for (int i = 1; i < classTypeConstraints.Count; i++) {
- if (classTypeConstraints[i].GetDefinition().IsDerivedFrom(result.GetDefinition()))
- result = classTypeConstraints[i];
+ if (HasValueTypeConstraint)
+ return this.Compilation.FindType(KnownTypeCode.ValueType);
+
+ List classTypeConstraints = new List();
+ foreach (IType constraint in this.DirectBaseTypes) {
+ if (constraint.Kind == TypeKind.Class) {
+ classTypeConstraints.Add(constraint);
+ } else if (constraint.Kind == TypeKind.TypeParameter) {
+ IType baseClass = ((ITypeParameter)constraint).EffectiveBaseClass;
+ if (baseClass.Kind == TypeKind.Class)
+ classTypeConstraints.Add(baseClass);
}
- return result;
}
+ if (classTypeConstraints.Count == 0)
+ return this.Compilation.FindType(KnownTypeCode.Object);
+ // Find the derived-most type in the resulting set:
+ IType result = classTypeConstraints[0];
+ for (int i = 1; i < classTypeConstraints.Count; i++) {
+ if (classTypeConstraints[i].GetDefinition().IsDerivedFrom(result.GetDefinition()))
+ result = classTypeConstraints[i];
+ }
+ return result;
}
- public IList EffectiveInterfaceSet {
+ ICollection effectiveInterfaceSet;
+
+ public ICollection EffectiveInterfaceSet {
get {
- throw new NotImplementedException();
+ var result = LazyInit.VolatileRead(ref effectiveInterfaceSet);
+ if (result != null) {
+ return result;
+ } else {
+ // protect against cyclic type parameters
+ using (var busyLock = BusyManager.Enter(this)) {
+ if (!busyLock.Success)
+ return EmptyList.Instance; // don't cache this error
+ return LazyInit.GetOrSet(ref effectiveInterfaceSet, CalculateEffectiveInterfaceSet());
+ }
+ }
+ }
+ }
+
+ ICollection CalculateEffectiveInterfaceSet()
+ {
+ HashSet result = new HashSet();
+ foreach (IType constraint in this.DirectBaseTypes) {
+ if (constraint.Kind == TypeKind.Interface) {
+ result.Add(constraint);
+ } else if (constraint.Kind == TypeKind.TypeParameter) {
+ result.UnionWith(((ITypeParameter)constraint).EffectiveInterfaceSet);
+ }
}
+ return result;
}
public abstract bool HasDefaultConstructorConstraint { get; }
diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs
index 22e7fc4fc8..f0ec26d0e1 100644
--- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs
+++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DummyTypeParameter.cs
@@ -189,7 +189,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return SpecialType.UnknownType; }
}
- IList ITypeParameter.EffectiveInterfaceSet {
+ ICollection ITypeParameter.EffectiveInterfaceSet {
get { return EmptyList.Instance; }
}