I have two classes, A and B. B inherits from A.
Here is my problem : I have a constant ConstantA which is useful for the class A, but also for the child classes. I also have a constant ConstantB, which is specific to my class B.
Since I store my constants in a public static nested class, the Constants class in the child class hides the parents one. I tried making it a partial class, it does not help. Is there any way to solve this?
Here's an example :
public class A
{
public static partial class Constants
{
public const int ConstantA = 1;
}
}
public class B : A
{
public static partial class Constants
{
public const int ConstantB = 1;
}
}
Thank you!
You would need to make A a partial class as well, and declare your B-specific constant separately from the B class itself:
public partial class A
{
public static partial class Constants
{
public const int ConstantA = 1;
}
}
public partial class A
{
public static partial class Constants
{
public const int ConstantB = 1;
}
}
public class B : A
{
static void M()
{
int i = Constants.ConstantB;
int j = Constants.ConstantA;
}
}
That said, I'm skeptical that design is all that good. It has the effect of declaring your ConstantB value inside A, which seems contrary to the goal of encapsulation, assuming ConstantB really is relevant only to class B. If you declare it this way, ConstantB is accessible via any use of the Constants class, in any type.
But if you're okay with that, and are just trying to make sure the declaration of the constant stays with the B class, then the above will work.
Other options include going ahead and hiding (using the new keyword) the base Constants class, with the minor inconvenience of having to specify the base class as fully-qualified to access the base values (e.g. A.Constants.ConstantA), hiding the base class and having the B.Constants class inherit A.Constants (requires abandoning the static class attribute) or, IMHO much better, not using a nested class at all, and instead putting the Constants classes in their respective namespaces.
Simply make your ConstantA an attribute of your parent class, putting this attribute in a nested class removes it from the scope of the inherited class.
If you really want nested classes, you can leave the static keyword, and do inheritance for the B.Constants nested class:
public class A
{
public class Constants
{
public const int ConstantA = 1;
}
}
public class B : A
{
public new class Constants : A.Constants
{
public const int ConstantB = 2;
}
}
The usage will be the same.
Related
I have two classes like Class A and Class B. Class A have some properties, methods and Class B have only the properties. But both Classes have the same set of properties.
My Question is, If I add any new property in Class A, I need to add that in Class B also. If I did not add means, need to show error. How can I achieve this through C#?
You may achieve this by using an Interface and implementing it both in class A and class B. In the interface, define the property that is required in class A and B:
public interface ICommonProperty
{
string MyProperty{ get; set; }
}
Or you can use keyword abstract to create a class in common for A and B.
abstract class BaseClass // Abstract class
{
public int X {get;set;} // property in common for 2 class
}
class A : BaseClass
{
}
class B : BaseClass
{
public int Y {get;set;} // other property of B
}
You can go with the abstract class. The abstract keyword enables you to create classes and class members that are incomplete and must be implemented in a derived class.
Here is a simple example related to your question However you can understand and learn about Abstract classes here : Abstract Class
using System;
public class Program
{
public static void Main()
{
A objA = new A();
objA.printA();
B objB = new B();
objB.printB();
}
}
abstract class Parent{
public int a = 5;
}
class A : Parent
{
public void printA()
{
Console.WriteLine("In class A, value is "+a);
}
}
class B : Parent
{
public void printB()
{
Console.WriteLine("In class B, value is "+a);
}
}
Output of the above program is:
In class A, vlaue is 5
In class B, vlaue is 5
Hope this helps you.
I have multiple classes. Each one have two constants defined (the constants values differ, but I know every class has this 2 constants). Those constants are used as values for a DbColumn Attribute (It's not possible to use Properties instead). I want to use this classes as generics in another class and get the value of the constants.
Here's a little example:
public abstract class BaseAssignment
{
//Won't work
public (abstract) const string Item;
public (abstract) const string AssignedItem;
}
public class AssignemtA : BaseAssignment
{
public const string Item = "A";
public const string AssignedItem = "1";
[DbColumn(Item)]
...
[DbColumn(AssignedItem)]
...
}
public class AssignmentB : BaseAssignment
{
public const string Item = "B";
public const string AssignedItem = "2";
[DbColumn(Item)]
...
[DbColumn(AssignedItem)]
...
}
public class AssignmentHandler<Tobj> where Tobj : BaseAssignment
{
public void Test()
{
Console.WriteLine(Tobj.AssignedItem);
}
}
The BaseAssignment class would not work, because it's not possible to define a abstract constant. Is there any possibility to solve this problem?
Abstract and constants are orthogonal. Constants are kind of static member, whereas abstract means it participates in inheritance and which should be a instance member.
My suggestion is to use abstract property. If you can't use properties, then you'll have to use reflection to read the constant value.
Here's how you do with reflection:
public class AssignmentHandler<TObj> where TObj : BaseAssignment
{
public void Test()
{
var assignedItemField = typeof(TObj).GetField("AssignedItem", BindingFlags.Static | BindingFlags.Public);
Console.WriteLine(assignedItemField .GetRawConstantValue());
}
}
Note:Even if you use abstract property, you can't use Tobj.AssignedItem. You need a instance of Tobj to read the property.
I'm a beginner in C#. I want to do the following:
Having class A in namespace nA I need to implement class B in namespace nB that inherits everything from A and adds some functionality, that's fine.
In ProjectA I have:
namespace nA{
public abstract class A{
public const int a = 1;
}
}
in ProjectB t I have:
using ProjectA.nA;
namespace nB{
class abstract B : A{
public const int b = 2;
}
}
and in ProjectC I have
using ProjectB.nB;
namespace nC{
class C{
void someMethod(){
int valueA = B.a //error, nB.B does not contain a definition for 'a'
int valueB = B.b //works just fine
}
}
}
Since it should work, I would suggest that you check you're not missing any assembly references in your projects.
Constants and static members are always accessed via the class that actually defines thems. A.a will work. Also note that it is accessible from any class, not just an inheritor.
In project B write:
using ProjectA.nA;
namespace nB{
class abstract B : A{
public const int a = A.a;
public const int b = 2;
}
}
Then project C should compile. Or one could do:
using ProjectB.nB;
namespace nC{
class C{
void someMethod(){
int valueA = ProjectA.nA.a;
int valueB = B.b;
}
}
}
Since ProjectC will have to reference ProjectA.
The better lesson here is to think in terms of separation of concerns. If class C should not know directly about class A, then it should also not now about a constant class A defines. Instead, there should be some functionality in B which uses the constant and makes sense for what class B is attempting to accomplish. Hence, what class B is concerned with that uses class A and provides this appropriate separation.
CODE :
public class A {
public const int beingSupportedRate = 0;
}
public partial class B : A {
public const int beingSupportedRate = 1;
}
I want it as explicitly as a const int because of performance.
Putting virtual in front of class A variable beingSupportedRate causes compiler error following :
The modifier 'virtual' is not valid for this item
You should use the new keyword to explicitly hide the inherited member:
public class A
{
public const int beingSupportedRate = 0;
}
public class B : A
{
public new const int beingSupportedRate = 1;
}
Remember that you cannot access the constant member from an instance.
Console.WriteLine(A.beingSupportedRate);
Console.WriteLine(B.beingSupportedRate);
Output:
0
1
There are some problems that you should consider when using this solution. Take the following console program, for example:
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
C c = new C();
a.GetBeingSupportRate();
b.GetBeingSupportRate();
c.GetBeingSupportRate();
Console.Read();
}
public class A
{
public const int beingSupportedRate = 0;
public void GetBeingSupportRate()
{
Console.WriteLine(beingSupportedRate);
}
}
public class B : A
{
public new const int beingSupportedRate = 1;
}
public class C : B
{
}
}
This will output 0 for all three class instances, since the inherited method uses the constant value in A. This means you will have to override all methods that reference the constant.
A preferred approach is to use an interface with a property that must be implemented and not use constants for this purpose.
Fields (including constants) can't be virtual. That has nothing to do with it being a constant... it's just the way fields work... although the fact that constants are implicitly static makes it even less feasible, as it were.
If you want polymorphic behaviour, it has to be via an instance member which is a property, method or event.
As an aside, I strongly suspect your "I want it as const for performance reasons" justification is bogus micro-optimization. It's not even clear how you're using this, but I very much doubt that you've tried it as a non-constant and proved that it's too slow.
Actually I believe you misunderstood the point of polymorphism in object-oriented programming.
Constants, fields and variables are just a storage (well, references, but I'm talking from the conceptual point of view).
Polymorphism is about changing the behavior of something. Overriding a constant couldn't be changing a behavior but changing its value.
Another point is a constant is static, thus it doesn't belong to an instance but there's an immutable single value in the AppDomain and it survives for the application life-cycle.
With the above statement, why you would want to override a constant like an instance member? Do you imagine the next situation?
public class A
{
public virtual const int Some = 1;
}
public class B : A
{
public override const int Some = 2;
}
public class C : A
{
// No override here!
}
int valueOfSomeConstant = C.Some;
Hold! If a constant is static, C.Some would be 2 even if C does override no constant!
Some quote from your question:
I want it as explicitly as a const int because of performance. [...]
This has only an answer: the premature optimization is the devil of any software development.
As Jon Skeet said, this is going to be the least of your issues.
Constants cannot be overridden, they are constant.
If you want this value to be alterable by extension then you'll need to use something less constant, with a nature of being changed per context, such as an abstract element to implement or virtual to override.
U Can do this i guess:
public class A
{
public virtual Int32 beingSupportedRate
{
get { return 0; }
}
}
public class B : A
{
public override Int32 beingSupportedRate
{
get { return 1; }
}
}
The case arises where one wants certain options to be publicly available, but others to only be internally or privately available within an assembly or class respectively.
What is the most elegant way of doing this?
The following would be perfect, but isn't possible:
public enum EActions
{
internal Shutdown,
Read,
Write,
Update
}
...
public void DoSomething(EActions action, int param2, int param3)
{
// act
}
...
public:
DoSomething(Read/Write/Update);
You can use Extensible enum and control the accessibility as desired.
Extensible Enum
As you tagged this question with design-patterns, I recommend that you replace this enum with a abstract base class, and replace the items with derived classes. Then create static instances in the base class for each child class.
public abstract class EAction
{
public abstract void DoYourDeal();
internal static readonly ShutDownEAction Shutdown = new ShutDownEAction() ;
public static readonly ReadEAction Read = new ReadEAction() ;
//...
}
public class ReadEAction : EAction {...}
public class WriteEAction : EAction {...}
public class UpdateEAction : EAction {...}
internal class ShutDownEAction : EAction {...}
public void DoSomething(EAction action)
{
action.DoYourDeal();
}