I have three classes which have many common properties, so I generated a base class from which they inherit:
public class CommonConfig
{
public TimeSpan Period1 { get; private set; }
public TimeSpan Period2 { get; private set; }
public TimeSpan Period3 { get; private set; }
};
public class Config1 : CommonConfig
{
public long count1 {get; private set; }
}
public class Config2 : CommonConfig
{
public long count2 {get; private set; }
}
I am not sure that I want to make CommonConfig to be public. Is it possible to keep it private but still make something that allows usage like below.
Config1 c1;
TimeSpan ts1 = c1.Period1;
No you can not, as to be able to access to the property of that class, you need to specify it public, and you can not specify private a class which properties are public .
Config1 c1;
TimeSpan ts1 = c1.Period1; // THIS PROPERTY HS TO BE PUBLIC
and if you
//MISMATCH BETWEEN CLASS AND ITS PROPERTIES ACCESS MODIFIERS
private class CommonConfig {
public TimeSpan Period1 { get; private set; }
public TimeSpan Period2 { get; private set; }
public TimeSpan Period3 { get; private set; }
}
and even more, you will get compiler error:
Elements defined in a namespace cannot be explicitly declared as
private, protected, or protected internal
As defining a class on the "top" level (on level of the namespace) you have to declare it public. If you want to hide it, you have to declare that class inside another class.
You cannot make a class private, internal is the most restrictive possible modifier for a non nested class.
Also you cannot have the access for descendant classes less restrictive than the parent class, so you have to stick with public for CommonConfig.
No You can not make it as private.
you can not access private class with public property.
you must specify Public class
If your aim is to prevent usage of the class CommonConfig directly, you could mark the class CommonConfig as abstract and also the properties within it (as required).
That way, though the class would be visible but the only way to use it would be via Config1 or Config2 .
See this for more details.
How about
public class CommonConfig
{
public TimeSpan Period1 {get; protected set;}
{
You could also make the whole attribute protected if needed...
Related
I was just coding a simple C# interface, and I put a property in it without thinking it through too far. For example:
public interface IMyInterface
{
string Name { get; set; }
object[][] Data { get; set;
}
I realized that I'm a little confused with properties when applied to interfaces and abstract base classes. In a normal class, this syntax would generate the accessor and mutator for a hidden string member that it generated behind the scenes.
Interfaces shouldn't be able to have data members. So, does this syntax do something different in that case?
What about for abstract classes? If I put this same syntax in the abstract base and the derived class, would both end up with a hidden member?
Interfaces shouldn't be able to have data members.
Those are properties, and those are allowed:
An interface contains only the signatures of methods, properties, events or indexers.
See also c# properties on Interface.
As for your second question:
If I put this same syntax in the abstract base and the derived class, would both end up with a hidden member?
Yes. You can prevent that by marking the property virtual on the base class and override on the derived class.
The property declaration in the interface is completely separate from the implementation. Thus you can implement it using automatic properties
private class MyImpl : IMyInterface
{
public string Name { get; set; }
public object[][] Data { get; set; }
}
or declare your own backing field
private class MyImplBacked : IMyInterface
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public object[][] Data { get; set; }
}
Same scenario in abstract classes
public abstract class MyAbstractClass
{
public abstract string Name { get; set; }
public abstract object[][] Data { get; set; }
}
private class MyImpl : MyAbstractClass
{
public override string Name { get; set; }
public override object[][] Data { get; set; }
}
private class MyImplBacked : MyAbstractClass
{
private string _name;
public override string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public override object[][] Data { get; set; }
}
Interfaces shouldn't be able to have data members. So, does this syntax do something different in that case?
Technically it's not a data member - it's a get/set method pair that has an underlying data member. There's no implementation.
What about for abstract classes? If I put this same syntax in the abstract base and the derived class, would both end up with a hidden member?
If the class is abstract and the property is virtual then yes, you will be overriding an auto-implemented property with another auto-implemented property (which is pointless).
If the class is abstract and the property is NOT virtual then you still have two implementations, but the base class is hiding the parent implementation rather than overriding it (which is still pointless if they're both auto-implemented).
If the property is abstract then the abstract class won't have an implementation. You'll have to implement the get/set in your concrete class (which could be auto-implemented bot doesn't have to be).
Does the new TypeInfo class include private members by default in its "DeclaredXXX" properties?
It returns both private and public members. However only ones that are declared at that level, any inherited members etc. will not be returned.
If it is a Property and not a Field it will show private members in DeclaredProperties
public class Test
{
private string test; // will not be in DeclaredProperties
private string test2 { get; set; } // will be in DeclaredProperties
public int test3{ get; set; } // will be in DeclaredProperties
}
var result = typeof(Test).GetTypeInfo().DeclaredProperties;
I want to propagate the property from child class to parent class,
ie: If MySchool.ModifiedTime is changed it should change the ModifiedTime in Student Class too, like wise LstBook[0].ModifiedTime is changed it should change MySchool.ModifiedTime as well Student.ModifiedTime... (basically ModifiedTime should be in sync),any Idea
I'm looking for a Generic function in BaseClass to achieve this.
public class MyBaseClass
{
public DateTime ModifiedTime{ get; set; }
}
public class Student: MyBaseClass
{
public string Name { get; set; }
public school MySchool {get;set;}
}
public class School : MyBaseClass
{
public string SchoolName { get; set; }
public List<Book> LstBook {get;set;}
}
public class Book:MyBaseClass
{
public string BookName{get;set;}
}
You could make ModifiedTime virtual and then in each child class override it to perform the syncing.
public class MyBaseClass
{
public virtual DateTime ModifiedTime{ get; set; }
}
public class Student: MyBaseClass
{
public string Name { get; set; }
public school MySchool {get;set;}
public virtual DateTime ModifiedTime
{
get {
return MySchool.ModifiedTime;
}
set {
MySchool.ModifiedTime = value;
}
}
}
And so on.
However, I would reconsider your class hierarchy because it seems like the factoring is incorrect. If all the properties need to be in sync across the entire hierarchy then maybe only one class should have that property and other classes should refere to it. For example, only School should have the ModifiedTime property and when you need to get the modified time for a student you would retrieve it through the MySchool property
You seem to be misunderstanding how object hierarchy works.
Implementing this as a class member only links it to the object created, and a static method would of course mean all objects access the same property.
Instead, as I understand it, you want groups of instances (not all) to share a property.
The simplest way to do this is to create a shared object that provides the modified time for all instances in a group.
As the other commenters have pointed out, you can't do this in a straightforward way with a base class simply because that's not how class hierarchies work. What you could do is create another class called "GroupInfo" or something like that. Make ModifiedTime a property on that.
In all your other classes, add a property for a GroupInfo. Then whenever you create a new book or whatever, as part of the constructor pass in a reference to the GroupInfo for the book.
That way all the objects in the group will share a single GroupInfo, and thus a single ModifiedTime.
You can make ModifiedTime static, which will cause it to be shared among all derived instances of MyBaseClass.
public class MyBaseClass
{
public static DateTime ModifiedTime{ get; set; }
}
Update: More complete example; better explanation of methodology
Your base class could be better described as a interface since your enforcing that each class implement a common property and not making common calculations or sweeping generalizations that could group schools, students, and books together.
Pursuing an event driven solution there are a few things you can do such as using BindingList<T> which is basically List<T> on steroids.
Unfortunatly, you'll need to explode your pretty little { get; set; } properties into full fields, but the best way is for each modification of a property to trigger an event. Each subsequent object that is affected by the modification is subscribed to your modified objects Modified event.
public interface IChangeAware
{
event EventHandler<EventArgs> OnChange;
DateTime ModifiedTime { get; set; }
}
public class Student : IChangeAware
{
public event EventHandler<EventArgs> OnChange;
public DateTime ModifiedTime { get; set; }
public string Name { get; set; }
public School School
{
get { return School; }
set
{
School = value;
if (this.OnChange != null)
this.OnChange(this, new EventArgs());
}
}
public Student()
{
if (School != null)
School.OnChange += MySchoolOnChange;
}
void MySchoolOnChange(object sender, EventArgs e)
{
ModifiedTime = DateTime.Now;
}
}
public class School : IChangeAware
{
public event EventHandler<EventArgs> OnChange;
public DateTime ModifiedTime { get; set; }
public string SchoolName { get; set; }
public BindingList<Book> Books { get; set; }
public School()
{
Books = new BindingList<Book>();
Books.ListChanged += BooksListChanged;
}
void BooksListChanged(object sender, ListChangedEventArgs e)
{
ModifiedTime = DateTime.Now;
OnChange(this, new EventArgs());
}
}
public class Book
{
public string BookName { get; set; }
}
I've recently implemented a singleton class, and within it I've declared a static generic list of (T) class. Anyway this is my first attempt at using singleton but everything I've tried work so far.
My Question: To be consistent, I don't want the MasterSiteData to be visible to other classes except my Singleton class. I thought of maybe encapsulating both classes within a parent class which would give me new options. However I'd rather have some of the great opinions you all provide :).
public sealed class Singleton
{
private static readonly Singleton Instance = new Singleton();
private Singleton()
{
}
public static List<MasterSiteData> MasterDetails = new List<MasterSiteData>();
}
public class MasterSiteData
{
public Guid GuidId { get; set; }
public string Uri { get; set; }
public int LinkNumber { get; set; }
public MasterSiteData(Guid guid, string uri, int linknumber)
{
GuidId = guid;
Uri = uri;
LinkNumber = linknumber;
}
}
EDIT:
Crap! I totally forgot that I need to instantiate the MasterSiteData class to add a record to my list, therefore I really can't have it hidden, for example
Singleton.MasterDetails.Add(new MasterSiteData(Guid.NewGuid(), "lol1", 1337));
Use an interface and make the implementation private to Singleton. (Also, don't use public fields, use properties):
public sealed class Singleton
{
public static List<ISiteData> Details { get; private set; }
private Singleton()
{
//create new instances of MasterSiteData and add to the list
}
private class MasterSiteData : ISiteData
{
public Guid GuidID {get;set;}
public string Uri {get;set;}
public int LinkNumber {get;set;}
public MasterSiteData(Guid guid, string uri, int linkNumber)
{
GuidID = guid;
Uri = uri;
LinkNumber = linkNumber;
}
}
}
public interface ISiteData
{
Guid GuidID {get;set;}
string Uri {get;set;}
int LinkNumber {get;set;}
}
In order to achieve the accessibility level you require, you will have to declare your MasterSiteData class inside the Singleton class, and mark it's accessibility level as private.
For example:
public class Singleton
{
private MasterSiteData innerClass = new MasterSiteData();
private class MasterSiteData
{
// your mastersitedata class
}
}
Since the Singleton class effectively "owns" the MasterSiteData class, it can create instances of the MasterSiteData class itself, however no code outside of the outer Singleton class can access or create instances of the MasterSiteData type.
I'd like to have the following setup:
class Descriptor
{
public string Name { get; private set; }
public IList<Parameter> Parameters { get; private set; } // Set to ReadOnlyCollection
private Descrtiptor() { }
public Descriptor GetByName(string Name) { // Magic here, caching, loading, parsing, etc. }
}
class Parameter
{
public string Name { get; private set; }
public string Valuie { get; private set; }
}
The whole structure will be read-only once loaded from an XML file. I'd like to make it so, that only the Descriptor class can instantiate a Parameter.
One way to do this would be to make an IParameter interface and then make Parameter class private in the Descriptor class, but in real-world usage the Parameter will have several properties, and I'd like to avoid redefining them twice.
Is this somehow possible?
Make it a private nested class that implements a particular interface. Then, only the outer class can instantiate it, but anyone can consume it (through the interface). Example:
interface IParameter
{
string Name { get; }
string Value { get; }
}
class Descriptor
{
public string Name { get; private set; }
public IList<IParameter> Parameters { get; private set; }
private Descriptor() { }
public Descriptor GetByName(string Name) { ... }
class Parameter : IParameter
{
public string Name { get; private set; }
public string Value { get; private set; }
}
}
If you really must avoid the interface, you can create a public abstract class that has all of the properties but declares a protected constructor. You can then create a private nested class that inherits from the public abstract that can only be created by the outer class and return instances of it as the base type. Example:
public abstract AbstractParameter
{
public string Name { get; protected set; }
public string Value { get; protected set; }
}
class Descriptor
{
public string Name { get; private set; }
public IList<AbstractParameter> Parameters { get; private set; }
private Descriptor() { }
public Descriptor GetByName(string Name) { ... }
private class NestedParameter : AbstractParameter
{
public NestedParameter() { /* whatever goes here */ }
}
}
LBushkin has the right idea. If you want to avoid having to retype all the properties just right-click the name of the class and choose "Refactor" > "Extract Interface", that should give you an interface that contains all those properties. (This works in VS 2008, I don't know about earlier versions.)
C# generally takes the approach that instead of avoiding redundant code, VS will just help you write it faster.
You could use a constructor marked Internal.
That way it's public to classes in the assembly, and private to classes outside of it.
Mark the class to be "protected" from instantiation (Parameter) with the StrongNameIdentityPermission attribute and the SecurityAction.LinkDemand option:
[StrongNameIdentityPermission(SecurityAction.LinkDemand, PublicKey="...")]
class Parameter
{
...
}
You will need to provide the appropriate public key. Because you are demanding a link-time (JIT-time, in fact) check on the Parameterclass, this means that it can only be used from an assembly that is signed with a strong name that uses the private key matching the public key that you supply in the attribute constructor above. Of course, you will need to put the Descriptor class in a separate assembly and give it a strong name accordingly.
I have used this technique in a couple of applications and it worked very well.
Hope this helps.
If you want only the Descriptor class to instantiate a Parameter, then you can make the Descriptor class a nested class of Parameter. (NOT the other way around) This is counterintuitive as the container or parent class is the nested class.
public class Parameter
{
private Parameter() { }
public string Name { get; private set; }
public string Value { get; private set; }
public static Parameter.Descriptor GetDescriptorByName(string Name)
{
return Parameter.Descriptor.GetByName(Name);
}
public class Descriptor
{ // Only class with access to private Parameter constructor
private Descriptor() { // Initialize Parameters }
public IList<Parameter> Parameters { get; private set; } // Set to ReadOnlyCollection
public string Name { get; private set; }
public static Descriptor GetByName(string Name) { // Magic here, caching, loading, parsing, etc. }
}
}
There is another way: check the call stack for the calling type.