Enforce getter setter access at the interface level - c#

I want to enforce access on getter or setter for a property at the interface level so that the same be followed in the class that implements it. I want to do something like below:
public interface IExample
{
string Name
{
get;
internal set;
}
}
public class Example : IExample
{
private string _name = String.Empty;
string Name
{
get
{
return _name;
}
internal set
{
_name = value;
}
}
}
But unfortunately from what I know this is not allowed in C#. I think that is because interface are meant to only expose what that is with a public access(I haven't the slightest idea!).
What I need here is a way to implement this using any other coding pattern (preferably using interface) which will help me to enforce specific access on getter or setter of a property in all of its implemented classes.
I googled this and tried to go through MSDN docs for this but had no luck!

Using internal on a setter is somewhat nasty anyway but if you really want to do it you could define a second interface that is itself internal AND make Example internal to your assembly.
public interface IExample
{
string Name
{
get;
}
}
internal interface IExampleInternal
{
string Name
{
set; get;
}
}
internal class Example : IExample, IExampleInternal
{
public string Name { get; set; } = string.Empty;
}
Now anything in the same assembly can take an IExampleInternal and outside only ever gets to see IExample. You do however have to list both interfaces on every class you create.

How about this? This can be a workaround:
// Assembly: A
public interface IExample
{
string Name { get; }
}
// Assembly: B
using A;
public abstract class Example : IExample
{
public string Name { get; protected internal set; }
}
public class SpecificExample : Example
{
public void UpdateName(string name)
{
// Can be set because it has protected accessor
Name = name;
}
}
class Program
{
static void Main(string[] args)
{
IExample e = new SpecificExample()
{
// Can be set because it has internal accessor
Name = "OutsideAssemblyA"
};
}
}
// Assembly: C
using A;
public abstract class Example : IExample
{
public string Name { get; protected internal set; }
}
public class AnotherSpecificExample : Example
{
public void UpdateName(string name)
{
// Can be set because it has protected accessor
Name = name;
}
}
class Program
{
static void Main(string[] args)
{
IExample e = new AnotherSpecificExample()
{
// Can be set because it has internal accessor
Name = "OutsideAssemblyA"
};
}
}
This works but you have to create (or copy-paste) the abstract class Example in every assembly in which you would like to create a specific implementation of it, e.g. SpecificExample or AnotherSpecificExample.

this is not possible. As everybody told you, interfaces are meant to define public access. How about the following code ?
public interface IExample
{
string Name
{
get;
}
}

Related

How do I implement multiple interfaces with public properties but private set methods?

I have two interfaces:
public interface IFooFile
{
string Name { get; }
}
public interface IFooProduct
{
string Name { get; }
}
I'm wanting to implement both with private sets:
public class AFooThing : IFooFile, IFooProduct
{
public string IFooFile.Name { get; private set; }
public string IFooProduct.Name { get; private set; }
}
But the access modifiers are creating the error:
The accessor of the "AFooThing.IFooFile.Name.set" must be more restrictive than the property or indexer "AFooThing.IFooFile.Name"
If I implement the class like this, I get no access modifier errors but I don't have the second interface:
public class AFooThing : IFooFile
{
public string Name { get; private set; }
}
I can't figure out how to have both interfaces implemented with the added "private set" without causing problems. What is the proper way to handle this?
You cannot use access modifiers for an explicit interface, it is public. Also you could not add set property as it does not exist in the interface. What you can do is achieve your goal by using backing fields, e.g.
public class AFooThing : IFooFile, IFooProduct
{
private string _fooFileName;
private string _fooProductName;
string IFooFile.Name => _fooFileName;
string IFooProduct.Name => _fooProductName;
public AFooThing()
{
_fooFileName = "FooFileName";
_fooProductName = "FooProductName";
}
}

Extending classes with additional properties

I have an class object from an external library that I want to add some additional properties to.
Let's say the external class is:
public class ExternalClass
{
public string EXproperty1 {get;set;}
public string EXproperty2 {get;set;}
public string EXproperty3 {get;set;}
public ExternalClass(){}
}
and I have a list of these object which gets populated as
List<ExternalClass> listOfExternalClass=new List<ExternalClass>();
listOfExternalClass=GetListOfExternalClass();
I can extend this class by creating a new class, adding the additional properties and making the external class a property.
public class NewClass
{
public ExternalClass ExternalClass {get;set;}
public string NewProperty1 {get;set;}
public string NewProperty2 {get;set;}
public NewClass(){}
public NewClass(ExternalClass externalClass){
this.ExternalClass=externalClass;
}
}
But to convert by original list of the external classes to a list of the new classes I would have to create a new list of new classes and iterate through the original list creating a new object and adding it to the list, like
List<NewClass> listOfNewClass=new List<NewClass>();
foreach(var externalClass in listOfExternalClass)
{
listOfNewClass.Add(new NewClass(externalClass));
}
I would then be able to access the external properties like
listOfNewClass.FirstOrDefault().ExternalClass.EXproperty1;
Can I do this with inheritance or is there a more efficient method?
Ideally I would like to end up with by calling the properties like:
listOfNewClass.FirstOrDefault().EXproperty1;
This can certainly be done with inheritance. Consider the following.
//Inherit from our external class
public class NewClass: ExternalClass
{
//Note we do not have a copy of an ExternalClass object here.
//This class itself will now have all of its instance members.
public string NewProperty1 {get;set;}
public string NewProperty2 {get;set;}
//If it has parameters include those parameters in NewClass() and add them to base().
//This is important so we don't have to write all the properties ourself.
//In some cases it's even impossible to write to those properties making this approach mandatory.
public NewClass()
{
}
}
Few things to know:
Your code is called a wrapper. This is because it "wraps" another class or group of classes.
You cannot inherit from class marked as sealed.
In C# classes are not sealed by default. If they're sealed the developer has intentionally prevented you from inheriting from the class. This is usually for a good reason.
If you can actually extend the External class that would be easy to accomplish:
public class NewClass: ExternalClass
{
public string NewProperty1 {get;set;}
public string NewProperty2 {get;set;}
public NewClass(){}
public NewClass(ExternalClass externalClass){
// you would have to copy all the properties
this.EXproperty1 = externalClass.EXproperty1;
}
}
Yes inheritance is what you are looking for:
public class ExternalClass
{
public string EXproperty1 { get; set; }
public string EXproperty2 { get; set; }
public string EXproperty3 { get; set; }
public ExternalClass() { }
}
public class NewClass:ExternalClass
{
public string NewProperty1 { get; set; }
public string NewProperty2 { get; set; }
public NewClass() { }
}
If you wish for (or need) delegation instead of a copy you can do:
public class NewClass
{
public ExternalClass ExternalClass {get;set;}
public string NewProperty1 {get;set;}
public string NewProperty2 {get;set;}
public string EXproperty1 {get { return this.ExternalClass.EXproperty1; };set{ this.ExternalClass.EXproperty1 = value; }; }
public string EXproperty2 {get { return this.ExternalClass.EXproperty2; };set{ this.ExternalClass.EXproperty2 = value; }; }
public string EXproperty3 {get { return this.ExternalClass.EXproperty3; };set{ this.ExternalClass.EXproperty3 = value; }; }
public NewClass(){}
public NewClass(ExternalClass externalClass){
this.ExternalClass=externalClass;
}
}
Instead of working against specific types, work against interfaces.
Below I am showing a mix of facade pattern and adapter pattern to 'transform' external data to a well-defined interface (IDocument), effectively abstracting things your are working on.
Example 1 : query about an interface
Here are the types you'll work against:
public interface IDocument {
string Name { get; set; }
}
public interface IMetadata {
string[] Tags { get; set; }
}
This is your own representation, should you need any:
public class RichDocument : IDocument, IMetadata {
public string Name { get; set; }
public string[] Tags { get; set; }
}
This is the wrapper against external data:
(a bastard mix of facade and/or adapter concepts)
public class ExternalClass {
public string Whatever { get; set; }
}
public class ExternalDocument : IDocument /* only a basic object */ {
private readonly ExternalClass _class;
public ExternalDocument(ExternalClass #class) {
_class = #class;
}
public string Name {
get { return _class.Whatever; }
set { _class.Whatever = value; }
}
}
And a demo on how to use all that:
internal class Demo1 {
public Demo1() {
var documents = new List<IDocument> {
new ExternalDocument(new ExternalClass()),
new RichDocument()
};
foreach (var document in documents){
var name = document.Name;
Console.WriteLine(name);
// see if it implements some interface and do something with it
var metadata = document as IMetadata;
if (metadata != null) {
Console.WriteLine(metadata.Tags);
}
}
}
}
Example 2 : query about a component
This is a bit more involved by pushing the concept to treat everything in an uniform manner, you can find it in .NET framework, game development or whatever ...
Definitions you'll work against:
public interface IContainer {
IList<IComponent> Components { get; }
}
public interface IComponent {
// it can be/do anything
}
Some components you'll query about:
public interface IDocument : IComponent {
string Name { get; set; }
}
public interface IMetadata : IComponent {
string[] Tags { get; set; }
}
Your 'internal' type:
public class Container : IContainer {
public Container() {
Components = new List<IComponent>();
}
public IList<IComponent> Components { get; }
}
Your 'wrapper' against external data:
public class ExternalClass {
public string Whatever { get; set; }
}
public class ExternalContainer : IContainer {
private readonly List<IComponent> _components;
public ExternalContainer(ExternalClass #class) {
_components = new List<IComponent> {new ExternalDocument(#class)};
}
public IList<IComponent> Components {
get { return _components; }
}
}
public class ExternalDocument : IDocument {
private readonly ExternalClass _class;
public ExternalDocument(ExternalClass #class) {
_class = #class;
}
public string Name {
get { return _class.Whatever; }
set { _class.Whatever = value; }
}
}
And a usage example:
public class Demo2 {
public Demo2() {
var containers = new List<IContainer> {
new ExternalContainer(new ExternalClass()),
new Container()
};
foreach (var container in containers) {
// query container for some components
var components = container.Components;
var document = components.OfType<IDocument>().FirstOrDefault();
if (document != null) {
Console.WriteLine(document.Name);
}
var metadata = components.OfType<IMetadata>().FirstOrDefault();
if (metadata != null) {
Console.WriteLine(metadata.Tags);
}
}
}
}
Notes
The problem with inheritance is that it is a very rigid approach and generally once you start doing it and at some point you hit a wall and want to revert, it's hard to get out of it.
By working against abstractions things are more flexible and things are decoupled.
Here are two examples that might incite you to change your approach:
Composition over inheritance
Using Components

Struggling to implement abstract property in derived class

This all got a little trickier than I had intended. I'm using the HistoricalReportWrapper class because I retrieve my data through an API which has made it not realistic to have HistoricalReport implement IReport directly.
public abstract class CormantChart : Chart
{
public abstract IReport Report { get; protected set; }
}
public abstract class HistoricalChart : CormantChart
{
public override HistoricalReportWrapper Report { get; protected set; }
public HistoricalChart(HistoricalChartData chartData) : base(chartData)
{
Report = GetHistoricalReport(chartData.ReportID);
}
protected HistoricalReportWrapper GetHistoricalReport(int reportID)
{
return SessionRepository.Instance.HistoricalReports.Find(historicalReport => int.Equals(historicalReport.ID, reportID));
}
}
public class HistoricalReportWrapper : IReport
{
public HistoricalReport inner;
public int ID
{
get { return inner.ID; }
set { inner.ID = value; }
}
public string Name
{
get { return inner.Name; }
set { inner.Name = value; }
}
public HistoricalReportWrapper(HistoricalReport obj)
{
inner = obj;
}
}
public interface IReport
{
string Name { get; set; }
int ID { get; set; }
}
The idea here is that when I am working inside of the HistoricalChart class I need to be able to access specific properties of the HistoricalReport. The rest of my program, however, only needs to have access to the HistoricalReport's ID and Name. As such, I would like to expose IReport's properties to the world, but then keep the details contained to the class.
As it stands, all the classes which inherit HistoricalChart generate a "does not implement inherited abstract member" as well as a warning on HistoricalChart indicating that I am hiding CormantChart's Report.
What's the proper way to declare this to achieve what I'd like?
Thanks
EDIT: Whoops, I missed an override. Now, when I try to override CormantChart Report I receive:
'CableSolve.Web.Dashboard.Charting.Historical_Charts.HistoricalChart.Report': type must be 'CableSolve.Web.Dashboard.IReport' to match overridden member 'CableSolve.Web.Dashboard.Charting.CormantChart.Report' C
EDIT2: Taking a look at C#: Overriding return types might be what I need.
Because
public HistoricalReportWrapper Report { get; protected set; }
is not an implementation of
public abstract IReport Report { get; protected set; }

Do inheritance right

I have class:
internal class Stage
{
public long StageId { get; set; }
public string StageName { get; set; }
public int? Order { get; set; }
public Stage()
{
Order = 0;
}
}
I have also:
public class GroupStage : Stage
{
private override long StageId { set { StageId = value; } }
public GroupStage() : base() { }
public void InsertStage(long groupId)
{
}
public static void SetStageOrder(long stageId, int order)
{
....
}
public static void DeleteStage(long stageId)
{
....
}
public static GroupStage[] GetStages(long groupId)
{
....
}
}
and:
public class TaskStage : Stage
{
public DateTime? Time { get; set; }
public TaskStage()
: base()
{
....
}
public static Stage GetNextTaskStage(Guid companyId, long taskId)
{
....
}
public static Stage[] GetTaskStages(Guid companyId, long taskId)
{
....
}
}
This is not working and I get the exception:
Inconsistent accessibility: base class Stage is less accessible than class GroupStage
I want Stage class to be private and without access except to GroupStage and TaskStage. I also want to make StageId be private in GroupStage and in TaskStage.
How can I do that without duplicate the members of Stage in GroupStage and in TaskStage?
You can't make a derived class more accessible than it's base class. What you can do is make TaskStage and GroupStage internal as well, then inherit and expose public interfaces so that only the interface is visible outside of your assembly.
public interface IGroupStage
{
public string StageName{ get; set; }
...
}
interal class GroupStage : IGroupStage
{
...
}
You need to make you Stage class public or protected. if you make it abstract it cant be instantiated on that level, so if its public you dont have to worry about it being created as a base class
Make it protected instead of private. If you make it protected, you let classes that inherit from it call methods on the base class, and inherit the base class members.
What you probably actually want is for Stage to be an abstract base class which, therefore, cannot directly be instantiated regardless of its accessibility modifier. Change your definition of Stage:
public abstract class Stage
{
protected long StageId { get; set; }
public string StageName { get; set; }
public int? Order { get; set; }
protected Stage()
{
Order = 0;
}
}
The protected modifier means that your derived classes will be able to access that member, but it will not be accessible outside those classes.

c# inheritance help

I am fairly new to inheritance and wanted to ask something. I have a base class that has lots of functionality that is shared by a number of derived classes.
The only difference for each derived class is a single method called Name. The functionality is the same for each derived class, but there is a need for the Name distinction.
I have a property in the base class called Name. How do I arrange it so that the derived classes can each override the base class property?
Thanks.
Declare your method as virtual
public class A
{
public virtual string Name(string name)
{
return name;
}
}
public class B : A
{
public override string Name(string name)
{
return base.Name(name); // calling A's method
}
}
public class C : A
{
public override string Name(string name)
{
return "1+1";
}
}
Use a virtual property:
class Base
{
public virtual string Foo
{
get;
set;
}
}
class Derived : Base
{
public override string Foo
{
get {
// Return something else...
}
set {
// Do something else...
}
}
}
You can declare it with a virtual or abstract keyword in the base class, then the derived class can over-ride it
you need to declare your property (in the base clase) as virtual
To enable each derived class to override the property you just need to mark the property as virtual
class Base {
public virtual Property1 {
get { ... }
set { ... }
}
}
Well I'm not sure from your description that inheritance is actually the right solution to the problem but here's how you make it possible for a property to be overridden:
class Base
{
public virtual string Name { get; set; }
}
But do you need it to be writable? A readonly property may make more sense in which case this might work:
class Base
{
public virtual string Name
{
get { return "BaseName"; }
}
}
class Derived : Base
{
public override string Name
{
get { return "Derived"; }
}
}
In the base class:
public virtual string Name { get; set; }
In the derived classes:
public override string Name { get; set; }
However, if the only difference between the classes is that they have different names, I'd argue that instead of inheritance you should just use the base class with the Name set in the constructor:
e.g.
public class MyObject
{
public string Name { get; private set; }
public enum ObjectType { TypeA, TypeB, ... }
public MyObject(ObjectType obType)
{
switch (obType)
{
case ObjectType.TypeA:
Name = "Type A";
// and so on
}
}
}

Categories