I've the following class:
namespace Warnings
{
public abstract class BaseWarningIntField : IWarningInnerDataField
{
public string PropName;
public string HeaderCaption;
public sealed WarningInnerDataType DataType
{
get { return WarningInnerDataType.Integer; }
}
}
}
I want the last property DataType to be not overridable, since that's the base class for a warning-detail field of type Integer, so it needs to always return the correct type WarningInnerDataType.Integer.
Anyway, the compiler give me the following error:
'Warnings.BaseWarningIntField.DataType' cannot be sealed because it is not an override
But, as far as I know the override does exactly the opposite of what I'm trying to achieve.
in C# all methods by default are non-virtual. You can't override non-virtual method in sub-classes. So leaving property as usual will safe you from subclass overriding it.
Sealed is a keyword used in class declaration for inheritance restrictions or is used to stop virtual chain of members of a class hierarchy. But again - this relates to virtual methods and properties.
Trying to override "normal" property in sub-class will result in compile error
'WarningIntField.DataType.get': cannot override inherited
member 'BaseWarningIntField.DataType.get' because it is not
marked virtual, abstract, or override
To answer you comment, I'll present some code examples to illustrate my point. You can't actually restrict derived classes from hiding a method or property. So next situation is legal and there is no way to overcome it (this related to virtual method and methods denoted with new keyword as well)
class BaseClass
{
public string Property {get; set;}
}
class DerivedClass : BaseClass
{
//compiler will give you a hint here, that you are hiding a base class prop
public string Property {get; set;}
}
The same way you can't restrict of hiding a field in a class by local variable, so this situation is also valid. Note that compiler will also help you to note, that you are hiding class field in by a local variable. This also related to readonly const and simple static fields as well.
int field = 0; //class field
void Foo()
{
int field = 0; //local variable
}
Related
Struggling a bit with inheritance here. I have common properties to use in two derived classes, so I made a base class LogBaseViewModel. I don't ever want this base class to be used except to be inherited by derived classes, so I made it protected (also tried private).
I found this bit, and maybe I'm mis-interpreting, but thought if I wrapped all 3 of these classes within one, they'd no longer be "outside" and hence this would be allowed.
From section 3.5.3 of the C# 5 specification:
When a protected instance member is accessed outside the program text
of the class in which it is declared, and when a protected internal
instance member is accessed outside the program text of the program in
which it is declared, the access must take place within a class
declaration that derives from the class in which it is declared.
Furthermore, the access is required to take place through an instance
of that derived class type or a class type constructed from it.
However, no joy, I get the error: Error CS0060 Inconsistent accessibility: base class 'LogViewModels.LogBaseViewModel' is less accessible than class 'LogViewModels.LogSearchViewModel'.
public class LogViewModels
{
protected class LogBaseViewModel
{
public int Id { get; set; }
public string Level { get; set; }
public string Message { get; set; }
public string Exception { get; set; }
}
public class LogSearchViewModel : LogBaseViewModel
{
public DateTime? FromDate { get; set; }
public DateTime? ToDate { get; set; }
}
public class LogViewModel : LogBaseViewModel
{
public System.DateTime Date { get; set; }
}
}
Applying the protected modifier on LogBaseViewModel would make it accessible only inside LogViewModels, and in subclasses of LogViewModels, not subclasses of LogBaseViewModel.
From here:
A protected member is accessible within its class and by derived class instances.
The "protected member" is the class LogBaseViewModel. "Its class" refers to the enclosing class LogViewModels.
By making LogBaseViewModel protected, you are telling the compiler that you don't want any external class to know about the insides of LogBaseViewModel. But then you said public class LogSearchViewModel : LogBaseViewModel. This allows people to access the insides of LogBaseViewModel through LogSearchViewModel! The compiler sees that this will make the protected modifier on LogBaseViewModel meaningless, so it gives you an error.
You said:
I don't ever want this base class to be used except to be inherited by derived classes.
Which is the use case for an abstract class. You should keep LogBaseViewModel public, and make it abstract.
I'm new to C#, so this is kind of hard for me to understand. System.Reflection.MemberInfo.Name property is stated as follows:
public abstract string Name { get; }
I understand that it is an auto-implemented property, but how the value of Name is set in the first place?
MemberInfo is a base class for others such as PropertyInfo. Derived classes override Name. You as a user of the reflection framework do not care that this is an abstract property. The Name is simply available for you to use.
Whether this is an auto-property or not is irrelevant and in fact you cannot find out. Auto-properties are a C# concept that disappears when compiled to IL.
The .NET Reflection system allows user code to derive their own classes from the typical reflection classes such as PropertyInfo. The framework provides default implementations. These default implementations (here: internal class RuntimePropertyInfo) provide an implementation for abstract members.
I'm not aware of anyone doing this or using this facility. It seems like a bad idea. I consider this to be a design bug in the .NET Framework.
MemberInfo is an abstract class, which means it cannot be instantiated itself, only subclasses of it can be. That allows for some of its members to also be abstract, and the Name property is one.
Subclasses of MemberInfo must define a public property called Name with a public get accessor. How the accessor is defined is up to the subclass.
All you have to know is that any class which inherits from MemberInfo will provide you with a Name property that you can access.
Here's an example of two classes which inherit from an abstract class with an abstract property.
abstract class Base {
public abstract string Name { get; }
}
class Derived1 : Base {
public override string Name { get { return "Foobar"; } }
}
class Derived2 : Base {
private string _name;
public override string Name { get { return _name; } }
public Derived2(string name) { _name = name; }
}
I couldn't understand the need or purpose of "protected" when i have "virtual/override" could someone explain me what do i need those 2 things if they are almost the same.
Edit:
Thanks for all the helpers, i now understand that "protected" is only for visibility purposes, while virtual/override is for class behavior.
They are certainly not almost the same.
The protected modifier sets the visibility of a field or method: such a member can only be accessed from the class it is defined in or from a derived class.
The virtual modifier specifies that the method it is applied to can be overridden in a derived class.
These modifiers can be combined: a method can be protected and virtual.
protected means private for current class and derived classes
virtual means it can be used as-is but also be overridden in derived classes
Maybe it is better with some code instead of things you have probably already read, here is a little sample you can play with. Try removing the comments (//) and you can see that the compiler tells you that the properties cannot be accessed
[TestFixture]
public class NewTest
{
[Test]
public void WhatGetsPrinted()
{
A a= new B();
a.Print(); //This uses B's Print method since it overrides A's
// a.ProtectedProperty is not accesible here
}
}
public class A
{
protected string ProtectedProperty { get; set; }
private string PrivateProperty { get; set; }
public virtual void Print()
{
Console.WriteLine("A");
}
}
public class B : A
{
public override void Print() // Since Print is marked virtual in the base class we can override it here
{
//base.PrivateProperty can not be accessed hhere since it is private
base.ProtectedProperty = "ProtectedProperty can be accessed here since it is protected and B:A";
Console.WriteLine("B");
}
}
I can be argued that the Most important distinction about virtual, is that this causes the compiler, when calling a method member polymorphically, which implementation to bind the compiled code to. When you call a member of a class from client code where the actual type of the object is, say derived class foo, but the variable it is being called on is actually typed (declared) as some base class, say bar, Members declared as virtual will bind to the implementation in the actual object type, (or to the most derived base class of the objects type that has an implementation). Members not declared as virtual will bind to the implementation in the type that the variable is declared to be.
A. Virtual. then, if the member is declared as virtual, the implementation in the derived class will be executed even if the variable is declared as a base type.
public class Animal
{ public virtual Move() { debug.Print("Animal.Move()"); }
public class Bird: Animal
{ public virtual override Move() { debug.Print("Bird.Move()"); }
Animal x = new Bird();
x.Move(); // Will print "Bird.Move"
B. Not Virtual. When a member which is not declared as virtual, then the implementation will be chosen based on the declared type of the variable the method is executed on. So if you have a Bird Object, in variable x declared as `Animal', and you call a method that is implemented in both classes, the compiler will bind to the implementation in the Animal class, not in Bird, even though the object is really a Bird.
public class Animal
{ public Move() { debug.Print("Animal.Move()"); }
public class Bird: Animal
{ public Move() { debug.Print("Bird.Move()"); }
Animal x = new Bird();
x.Move(); // Will print "Animal.Move"
I think you need to understand above two things properly, since both has different purpose.
protected is the type or member can only be accessed by code in the same class or struct, or in a derived class.
The virtual keyword is for modify a method, property and allow it to be overridden in a derived class.
In "The C# Programming Language" book Eric Lippert mentioned this:
A subtle point here is that an overridden virtual method is still considered to be a method of the class that introduced it, and not a method of the class that overrides it.
What is the significance of this statement? Why does it matter if the overridden virtual method is considered to be a method of the class that introduced it (or otherwise) since the overridden method will never be called unless you are dealing with the derived class?
It matters when you have a reference of one type pointing to an object of a different type.
Example:
public class BaseClass {
public virtual int SomeVirtualMethod() { return 1; }
}
public class DerivedClass : BaseClass {
public override int SomeVirtualMethod() { return 2; }
}
BaseClass ref = new DerivedClass();
int test = ref.SomeVirtualMethod(); // will be 2
Because the virtual method is a member of the base class, you can call the overriding method with a reference of the base class type. If it wasn't, you would need a reference of the derived type to call the overriding method.
When you are shadowing a method instead of overriding it, the shadowing method is a member of the derived class. Depending on the type of the reference you will be calling the original method or the shadowing method:
public class BaseClass {
public int SomeMethod() { return 1; }
}
public class DerivedClass : BaseClass {
public new int SomeMethod() { return 2; }
}
BaseClass ref = new DerivedClass();
int test = ref.SomeMethod(); // will be 1
DerivedClass ref2 = ref;
int test2 = ref2.SomeMethod(); // will be 2
Here's the full quote from the book:
A subtle point here is that an overridden virtual method is still considered to be a method of the class that introduced it, and not a method of the class that overrides it. The overload resolution rules in some cases prefer members of more derived types to those in base types; overriding a method does not "move" where that method belongs in this hierarchy.
At the very beginning of this section, we noted that C# was designed with versioning in mind. This is one of those features that helps prevent "brittle base-class syndrome" from causing versioning problems.
The full quote makes it clear that Eric Lippert is talking specifically about method overloading, not just about how virtual methods work.
As an example, consider the following program:
class Base
{
public virtual void M2(int i) { }
}
class Derived : Base
{
public void M1(int i) { Console.WriteLine("Derived.M1(int)"); }
public void M1(float f) { Console.WriteLine("Derived.M1(float)"); }
public override void M2(int i) { Console.WriteLine("Derived.M2(int)"); }
public void M2(float f) { Console.WriteLine("Derived.M2(float)"); }
public static void Main()
{
Derived d = new Derived();
d.M1(1);
d.M2(1);
}
}
I think many developers would be surprised that the output is
Derived.M1(int)
Derived.M2(float)
Why would d.M2(1) invoke Derived.M2(float) even though Derived.M2(int) is a better match?
When the compiler is determining what the M1 in d.M1(1) refers to, the compiler sees that both M1(int) and M1(float) are introduced in Derived, so both overloads are applicable candidates. The compiler selects M1(int) over M1(float) as the best match for the integer argument 1.
When the compiler is determining what the M2 in d.M2(1) refers to, the compiler sees that M2(float) is introduced in Derived and is an applicable candidate. According to the overload resolution rules, "methods in a base class are not candidates if any method in a derived class is applicable". Because M2(float) is applicable, this rule prevents M2(int) from being a candidate. Even though M2(int) is a better match for the integer argument and even though it's overridden in Derived, it's still considered to be a method of Base.
Understanding that an overridden virtual method belongs to the class which introduces it, rather than the class that overrides it, makes it easier to understand the way class members are bound. Except when using dynamic objects, all bindings in C# are resolved at compile time. If a BaseClass declares a virtual method foo, and DerivedClass:BaseClass overrides foo, code which attempts to call foo on a variable of type BaseClass will always be bound to virtual method "slot" BaseClass.foo, which will in turn point to the actual DerivedClass.foo method.
This understanding can be especially important when dealing with generics, since in C#, unlike C++, members of generic types are bound according to the generics' constraints, rather than according to the concrete generic types. For example, suppose there were a SubDerivedClass:DerivedClass which created a new virtual method foo(), and one defined a method DoFoo<T>(T param) where T:BaseClass {param.foo();}. The param.foo() call would be bound to BaseClass.foo even if the method were invoked as DoFoo<SubDrivedClass>(subDerivedInstance). If the parameter were cast to SubDerivedClass before invoking foo, the call would be bound to SubDrivedClass.foo(), but the compiler can't tell when producing DoFoo<T> that T will be anything more specific than BaseClass, it can't bind to anything that doesn't exist in BaseClass.
Incidentally, there are times it would be useful if a class could simultaneously override a base-class member and create a new one; for example, given an abstract base class ReadableFoo with some abstract read-only property, it would be helpful if a class MutableFoo could both provide an override for that property and define a read-write property with the same name. Unfortunately, .net does not allow that. Given such a restriction, the best approach may be for ReadableFoo to provide a concrete non-virtual read-only property which calls an protected abstract method with a different name to get the value. That way, a derived class could shadow the read-only property with a read-write one (that would call the same virtual method for reading, or a new (possibly virtual) method for writing.
(following is untested)
class BaseClass
{
public virtual void foo() {Console.WriteLine("BaseClass.Foo");
}
class DerivedClass:BaseClass
{
public override void foo() {Console.WriteLine("Derived.Foo");
}
class SubDerivedClass:DerivedClass
{
public new virtual void foo() {Console.WriteLine("SubDerived.Foo");
}
class MegaDerivedClass:SubDerivedClass
{
public override void foo() {Console.WriteLine("MegaDerived.Foo");
}
void DoFoo1<T>(T param) where T:BaseClass
{
param.foo();
}
void DoFoo1<T>(T param) where T:SubDerivedClass
{
param.foo();
}
void test(void)
{
var megaDerivedInstance = new MegaDerivedClass();
DoFoo1<MegaDerivedClass>(megaDerivedInstance);
DoFoo2<MegaDerivedClass>(megaDerivedInstance);
}
A SubDerivedClass has two virtual foo() methods: BaseClass.foo() and SubDerivedClass.foo(). A MegaDerivedClass has those same two methods. Note that classes derived from SubDerivedClass() which attempt to override foo will override SubDerivedClass.foo() and will not affect BaseClass.foo(); with the declarations as above, no derivative of SubDerivedClass can override BaseClass.Foo. Note also that casting an instance of SubDerivedClass or a subclass thereof to DerivedClass or BaseClass will expose the BaseClass.foo virtual method for calling.
Incidentally, if the method declaration in SubDerivedClass had been friend new virtual void foo() {Console.WriteLine("SubDerived.Foo");, it would be impossible for other classes within the same assembly to override BaseClass.foo() (since any attempt to override foo() would override SubDerivedClass.foo()), but classes outside the assembly which derive from SubDerivedClass wouldn't see SubDerivedClass.foo() and could thus override BaseClass.foo().
I tried to inherit interface, and make some of the automatically generated set property as private. This is an example.
public class MyClass
{
public interface A
{
int X {get; set;}
}
public interface B : A
{
int Y {get; set;}
}
public class C : A
{
public int X {get; private set;}
}
When I tried to compile it. I got an error 'MyClass.C' does not implement interface member 'MyClass.A.X.set'. 'MyClass.C.X.set' is not public..
I tried with private set; in iterface A, but I got this error again : 'MyClass.A.X.set': accessibility modifiers may not be used on accessors in an interface.
Is this accessibility modifier not allowed in C#?
I tried with private set; in iterface A, but I got this error again
If your interface only requires that a property should be retrievable, you define it as:
public interface A
{
int X {get;} // Leave off set entirely
}
The declaration of an interface defines the public set of members that the implementing type must have. So, if C implements A, it must have a public member for each member defined by the interface.
A defines that any implementing type must have a public property X with a public getter and a public setter. C does not meet this requirement.
You can think of an interface as the minimum functionality that your class must implement. If the interface specifies that a property exposes a get and a set clause, then you must implement a public get and set clause in your class, because only public methods and properties can implicitly implement interfaces.
You can simply leave out the set keyword in the interface property definition if you don't want to expose a public mutator. Then you can make the implementation mutator either public or private.
No it is not allowed. Remember, code which is using an instance of class C must be able to treat it as an interface A, which means that the contract is a public getter and setter for property X.
This applies to class inheritance as well as interface inheritance -- you must follow the contract of the type you are derived from.
If the intent of the code is that property X should not have a public setter, then the interface should be defined with just the { get; }
I believe interface members must be public if the interface itself is public. Your implementation of the property is faulty because of that.