When I have a public interface
public interface IPub { string Foo { get; set; } }
then I can implement this interface either by doing it explicitly:
public class CFoo : IPub { string IPub.Foo { get; set; } }
or implicitly by using the public modifier:
public class CFoo : IPub { public string Foo { get; set; } }
. Makes sense: The modifier must be public because the interface is public.
But when I have an internal interface
internal interface IInt { string Bar { get; set; } }
then I can only implement it explicitly:
public class CBar : IInt { string IInt.Bar { get; set; } }
or implicitly with the public modifier:
public class CBar : IInt { public string Bar { get; set; } }
, but NOT with the internal modifier:
public class CBar : IInt { internal string Bar { get; set; } }
// compiler error:
// 'CBar' does not implement interface member 'IInt.Bar'.
// 'CBar.Bar' cannot implement an interface member
// because it is not public.
This make no sense. Why do I need a public modifier when the interface is only internal? Are there any technical reasons why public must always be used in implicit interface implementations, or could the C# developers have made it differently (without needing to change a lot of things in the language)?
The modifier must be public because the interface is public.
While that would have been a way of determining it: that isn't what the compiler wants. For implicit interface implementation (regardless of the visibility of the interface type), a member must be declared as public, no "ifs", "buts" or "maybes" (the implementing type, however, can be any visibility level)
Absolutely the language designers could have looked at more complex rules, but: since there is also an option for explicit interface implementation, they presumably didn't feel that it was necessary to do so.
Specifically, this is ยง18.6.5 ("Interface mapping") in the specification (v5) - emphasis mine ("I"=interface type, "M"=member, "S"=implementing type):
If S contains a declaration of an explicit interface member implementation that matches I and M, then
this member is the implementation of I.M.
Otherwise, if S contains a declaration of a non-static public member that matches M, then this member
is the implementation of I.M. If more than one member matches, it is unspecified which member is
the implementation of I.M. This situation can only occur if S is a constructed type where the two
members as declared in the generic type have different signatures, but the type arguments make their
signatures identical.
Related
This is class design question.
I have main abstract class
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestriction<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestriction<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestriction<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}
BlockRule rule=new BlockRule();
TimeRestriction t=new TimeRestriction();
AgeRestriction a=new AgeRestriction();
rule.Restrictions.Add(t);
rule.Restrictions.Add(a);
I have to use non-generic Interface IRestriction just to avoid specifying generic type T in main abstract class. I'm very new to generics. Can some one let me know how to better design this thing?
Your approach is typical (for example, IEnumerable<T> implements IEnumerable like this). If you want to provide maximum utility to consumers of your code, it would be nice to provide a non-generic accessor on the non-generic interface, then hide it in the generic implementation. For example:
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions { get; set; }
}
public interface IRestriction
{
object Limit { get; }
}
public interface IRestriction<T> : IRestriction
where T:struct
{
// hide IRestriction.Limit
new T Limit {get;}
}
public abstract class RestrictionBase<T> : IRestriction<T>
where T:struct
{
// explicit implementation
object IRestriction.Limit
{
get { return Limit; }
}
// override when required
public virtual T Limit { get; set; }
}
public class TimeRestriction : RestrictionBase<TimeSpan>
{
}
public class AgeRestriction : RestrictionBase<TimeSpan>
{
}
public class BlockRule : AbstractBlockRule
{
public override List<IRestriction> Restrictions { get; set; }
}
I also showed using a base restriction class here, but it is not required.
The runtime treats IRestriction<TimeSpan> and IRestriction<int> as different distinct classes (they even have their own set of static variables). In your case the only classes common to both IRestriction<TimeSpan> and IRestriction<int> in the inheritance hierarchy are IRestriction and object.
So indeed, having a list of IRestriction is the only sensible way to go.
As a side note: you have a property Limit in there that you might want to access regardless of whether you're dealing with an IRestriction<TimeSpan> or IRestriction<int>. What I would do in this case is to define another property object Limit { get; } on IRestriction, and hide it in the actual implementation. Like this:
public interface IRestriction
{
object Limit { get; }
}
public interface IRestriction<T> : IRestriction
where T : struct
{
new T Limit { get; set; }
}
public class TimeRestriction : IRestriction<TimeSpan>
{
public TimeSpan Limit { get; set; }
// Explicit interface member:
// This is hidden from IntelliSense
// unless you cast to IRestriction.
object IRestriction.Limit
{
get
{
// Note: boxing happens here.
return (object)Limit;
}
}
}
This way you can access Limit as object on all your IRestriction when you don't care what type it is. For example:
foreach(IRestriction restriction in this.Restrictions)
{
Console.WriteLine(restriction.Limit);
}
Interfaces are contracts that need to be followed by the entity that implements the contract.
You have created two contract with the same name IRestriction
As far as I can see, what you are basically may need is a flag for classes that can be restricted, which should implement the IRestriction non-generic interface.
The second interface seems to be restrictable objects that also contain a limit property.
Hence the definition of the second IRestriction interface can be ILimitRestriction or whatever name suits your business needs.
Hence ILimitRestriction can inherit from IRestriction which would mark classes inheriting ILimitRestriction still objects of IRestriction
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestrictionWithLimit<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestrictionWithLimit<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestrictionWithLimit<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}
How can I separately declare a getter and a setter for a property?
For exemple, say I want to create the following hierarchy:
interface IReadOnlyFoo
{
string Value { get; }
}
interface IFoo : IReadOnlyFoo
{
string Value { set; }
}
class BasicFoo : IFoo
{
string Value { get; set; }
}
The compiler is compaining because IFoo.Value is hiding IReadOnlyFoo.Value, which is not what I want to do. I want to "merge" the getter and setter declarations.
I've had a look at how the .NET Framwork declares the IReadOnlyList and IList interfaces, but it's done in a different way.
How could I acheive what I want to do ? Can I do that with a property or do I really have to create separate GetValue() and SetValue() methods instead?
When you change your interface definition to
interface IReadOnlyFoo
{
string Value { get; }
}
interface IReadWriteFoo
{
string Value { get; set; }
}
class BasicFoo : IFoo, IReadOnlyFoo
{
public string Value { get; set; }
}
it should work.
When you implement the interface the two members would be merged since you don't have a get method in IFoo.Value.
interface IReadOnlyFoo
{
string Value { get; }
}
interface IFoo : IReadOnlyFoo
{
new string Value { set; }
}
class BasicFoo : IFoo
{
public string Value { get; set; }
}
As long as you are using implicit implementations for the interfaces it would behave as you intended. on the other hand, if you wish to have two different behaviors for the members of the interface then you want to use explicit implementations. You can find an example here
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/how-to-explicitly-implement-members-of-two-interfaces
All you have to change in your code is to add a getter to the Value property in the IFoo interface.
Semantically speaking, IFoo is a specific kind of IReadOnlyFoo that adds another capability to it's base type (the Setter of the Value property).
This is the exact definition of inheritance in object oriented programming - a child type is a more specific version of it's base type and is adding capabilities to it.
interface IReadOnlyFoo
{
string Value { get; }
}
interface IFoo : IReadOnlyFoo
{
new string Value { get; set; }
}
class BasicFoo : IFoo
{
public string Value { get; set; }
}
This code is perfectly valid and will give you exactly what you're looking for.
This way, if you have a reference of type IReadOnlyFoo to an instance of BasicFoo, the Value property is indeed readonly, but if your reference type is IFoo it's a read / write property.
You can see a live demo on rextester.
As per title, and just to deeper understand the reasons, why does in c# interface forces you to manually implement the its members, whereas abstract class doesn't?
I found Reasons not to use abstract class instead of interface?, but it seems to cover just part of the answer exhaustive.
public abstract class Bar
{
public int MemberA {get;set;}
public string MemberB {get;set;}
}
public interface IBar
{
public int MemberA {get;set;}
public string MemberB {get;set;}
}
Implement this is fine:
public class Foo1 : Bar
{
}
Implementing this raises a compile error:
public class Foo2 : IBar
{
}
Error:
'Foo2' does not implement interface member 'IBar.MemberA'
'Foo2' does not implement interface member 'IBar.MemberB'
I have the following interface:
public interface IAgable {
int Age { get; internal set; }
}
I want the Age property, to be read-only for external assemblies that reference this interface, but also I want the Age property to be set on the interface's same assembly, hence the internal modifier.
This, however, seems to throw a compilation error, as accessibility modifiers may not be used on accessors in an interface.
I want the property to be called from an interface, and I want to be able to set it at an internal level. At the same time, if referenced from an outside project, I want it to be readonly.
Is this possible?
Have an internal interface that provides both a get and a set, and a public interface that provides only a get. Have the public interface extend the internal interface:
public interface IAgable
{
int Age { get; }
}
internal interface IAgableInternal : IAgable
{
int Age { set; }
}
This is not possible according to Microsoft
Interfaces declared directly within a namespace can be declared as public or internal and, just like classes and structs, interfaces default to internal access. Interface members are always public because the purpose of an interface is to enable other types to access a class or struct. No access modifiers can be applied to interface members.
http://msdn.microsoft.com/en-us/library/ms173121.aspx
Try this:
public interface IAgeable {
MyAge {get;set}
}
public class MyAge:IAgeable{
public MyAge(int age){
MyAge = age;
}
int MyAge { get; internal set; }
}
Why is it allowed to change the visibility and existence of getters or setters in a property when implementing an interface?
interface IFoo
{
string Bar { get; }
}
class RealFoo : IFoo
{
public RealFoo(string bar)
{
this.Bar = bar;
}
public string Bar { get; private set; }
}
class StubFoo : IFoo
{
public string Bar { get; set; }
}
...and not legal to do the same when implementing an abstract class?
abstract class AbstractFoo : IFoo
{
public abstract string Bar { get; }
}
class RealFoo : AbstractFoo
{
public RealFoo(string bar)
{
this.Bar = bar;
}
// Cannot override because 'Bar' does not have an overridable set accessor
public override string Bar { get; private set; }
}
The interface declares what public properties the class must have (It's just a contract). Which means you need to have those properties, but can add to them.
The abstract class declares the actual structure of those properties. So if you don't have the setter in the abstract base, you can't add to it in the implementation.
When you write the override modifier it looks in the base class for something to override.
It perhaps becomes clearer if you think of the getters and setters as the methods that they eventually become.
In the case of the interface you are defining this:
interface IFoo
{
string GetBar();
}
Which can be read as "all classes that implement this interface must include this method."
Both of your classes do:
class RealFoo : IFoo
{
public string GetBar();
private void SetBar(string value);
}
they also implement SetBar(), but that is immaterial; they have fulfilled the contract defined by the interface and are valid.
The abstract class, on the other hand is this:
abstract class AbstractFoo : IFoo
{
public abstract string GetBar();
}
Which means that all child classes must provide a method body for GetBar()
The class you made is this:
class RealFoo : AbstractFoo
{
public override string GetBar();
public override void SetBar(string value);
}
By putting the override modifier in front of the SetBar method the compiler is expecting to find an abstract or virtual version in the base class. You don't have that so the compilation fails.
An abstract class is a class that cannot be instantiated, but must be inherited from. An abstract class may be fully implemented, but is more usually partially implemented or not implemented at all, thereby encapsulating common functionality for inherited classes.
An interface, by contrast, is a totally abstract set of members that can be thought of as defining a contract for conduct. The implementation of an interface is left completely to the developer.
Taken from the MSDN
http://msdn.microsoft.com/en-us/library/scsyfw1d(v=VS.71).aspx
According to the C# specification
An accessor that is used to implement
an interface may not have an
accessor-modifier. If only one
accessor is used to implement an
interface, the other accessor may be
declared with an accessor-modifier:
public interface I
{
string Prop { get; }
}
public class C: I
{
public Prop {
get { return "April"; } // Must not have a modifier here
internal set {...} // Ok, because I.Prop has no set accessor
}
}
That means it is OK to have an access modified on a class implementing the interface. However, the abstract class declares an implementation and you cannot change that with a derived class.