Reputation: 5126
This is a two-part question. First, which of these explicit property implementations gets bound to IAllTogether.SomeInt
and why doesn't the compiler complain about ambiguity? It does when you comment-out the marked lines.
public interface IFirst
{
int SomeInt { get; }
}
public interface ISecond
{
int SomeInt { get; }
}
public interface ICombined : IFirst, ISecond
{
new int SomeInt { get; } // Comment this line.
}
public interface IAllTogether : IFirst, ISecond, ICombined
{ }
public sealed class Implementation : IAllTogether
{
int ICombined.SomeInt { get { return 0; } } // Comment this line.
int IFirst.SomeInt { get { return 0; } }
int ISecond.SomeInt { get { return 0; } }
}
IAllTogether t = new Implementation();
var unimportant = t.SomeInt;
Second question would be: how do I find the right PropertyInfo
when given an interface Type
and a name of the property? I can use GetInterfaces()
and GetProperty()
to list all the possible candidates, but how do I know which is the right one? I tried typeof(IAllTogether).GetProperty("SomeInt")
, but it doesn't work.
Looks like the answer to the first part is that the hiding of inherited members resolves ambiguity. However, not even a single comment yet on the second part: how to reliably find the proper PropertyInfo
for some property name and an interface type.
Clarification on the second part of the question. What I'm looking for is a way to get the right property for any unknown Type
. Basically, a method like this:
public static PropertyInfo GetPropertyOfInterface(Type interfaceType, string propertyName)
{
if (!interfaceType.IsInterface)
throw new ArgumentException();
// for interfaceType == typeof(IAllTogether), return ICombined.SomeInt
// for interfaceType == typeof(IFirst), return IFirst.SomeInt
}
Upvotes: 0
Views: 179
Reputation: 5126
Lots of people answered the first part: if an interface hides members of the original interface, those are not considered.
Using that information, here's my attempt at the second part. Comments on issues or improvements are welcome.
public static PropertyInfo GetPropertyOfInterface(Type interfaceType, string propertyName)
{
if (interfaceType == null)
throw new ArgumentNullException("interfaceType");
if (!interfaceType.IsInterface)
throw new ArgumentException(
string.Format("Type {0} doesn't represent an interface.",
interfaceType.FullName),
"interfaceType");
// If declared in given interface, just return that.
var declaredProperty = interfaceType.GetProperty(propertyName);
if (declaredProperty != null)
return declaredProperty;
// Otherwise, first finding all the candidates.
var candidates = new HashSet<PropertyInfo>(
interfaceType.GetInterfaces().Select(t => t.GetProperty(propertyName)));
candidates.Remove(null);
if (candidates.Count == 0)
throw new ArgumentException(
string.Format("Property {0} not found in interface {1}.",
propertyName, interfaceType.FullName),
"propertyName");
// Finally, removing all candidates the first candidates hide.
var originalCandidates = candidates.ToList();
candidates.ExceptWith(
originalCandidates.SelectMany(prop => prop.DeclaringType.GetInterfaces())
.Select(t => t.GetProperty(propertyName)));
if (candidates.Count != 1)
throw new AmbiguousMatchException(
string.Format("Property {0} is ambiguous in interface {1}.",
propertyName, interfaceType.FullName));
return candidates.First();
}
Upvotes: 1
Reputation: 6891
To answer your first question.
Compiler only need to know is that the interface members are implemented or not. It is the runtime who decides which version of the member to invoke.
In your example you are using explicit implementation.
In this case compile first checks if SomeInt
property is implemented or not. If that is implicitly implemented it won't complain. If any one of the interface property is implemented explicitly compiler will check if rest o the interface properties are implemented either by implicit or explicit.
Upvotes: 0