Is there a way to force the override of a virtual method if another method is overriden?
public class BaseClass
{
protected virtual void A()
{
// a default action called first
}
protected virtual void B()
{
// a default action called second that,
// if A was overriden, makes no sense
}
}
EDIT
Thanks a lot for the Answers. It's very interresting to see how this could be achieved, but for my explicit case it's not critically important.
Also, i forgot to mention how those Methods would be used: (in BaseClass)
pulbic bool EditEntity(Guid id)
{
A();
// Some code that edits Entites
B();
}
No, you cannot. But this makes me think how could you achieve the same concept?
The best idea I came up with was declaring an interface which had the package of methods to override.
public interface IMyOverridablePackage
{
void A_Override();
void B_Override();
}
Then give the base class a protected method where the child class can explicitly override the set of methods.
protected void SetOverride(IMyOverridablePackage overridablePackage)
{
_overridablePackage = overridablePackage;
}
So then here's two classes, one which does and one which does not override the set of methods:
public class NotOverriding : MyBaseClass
{
}
public sealed class Overriding : MyBaseClass, IMyOverridablePackage
{
public Overriding()
{
SetOverride(this);
}
void IMyOverridablePackage.A_Override()
{
Console.WriteLine("Overriding.A_Override");
}
void IMyOverridablePackage.B_Override()
{
Console.WriteLine("Overriding.B_Override");
}
}
And the implementation of the base class:
public abstract class MyBaseClass
{
private IMyOverridablePackage _overridablePackage;
public void A()
{
_overridablePackage.A_Override();
}
public void B()
{
_overridablePackage.B_Override();
}
private class MyDefaultPackage : IMyOverridablePackage
{
private readonly MyBaseClass _myBaseClass;
internal MyDefaultPackage(MyBaseClass myBaseClass)
{
_myBaseClass = myBaseClass;
}
void IMyOverridablePackage.A_Override()
{
_myBaseClass.A_Impl();
}
void IMyOverridablePackage.B_Override()
{
_myBaseClass.B_Impl();
}
}
protected MyBaseClass()
{
_overridablePackage = new MyDefaultPackage(this);
}
private void A_Impl()
{
Console.WriteLine("MyBaseClass.A_Impl");
}
private void B_Impl()
{
Console.WriteLine("MyBaseClass.B_Impl");
}
protected void SetOverride(IMyOverridablePackage overridablePackage)
{
_overridablePackage = overridablePackage;
}
}
This does achieve the goal, but of course you have to ask 'how much to I want it?' Is it worth the extra code?
Here's a working dotnetfiddle: https://dotnetfiddle.net/xmPn20
Maybe you cannot force it via compiler errors, but you could write a test which asserts that the methods are in sync via some attributes. It would also be visible that there is some dependency.
A crude example would be something like this:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class VersionAttribute : Attribute
{
public VersionAttribute(string version)
{
Version = version;
}
public string Version { get; set; }
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class DependentAttribute : Attribute
{
public string DependentOnMethod { get; set; }
public string DependentOnVersion { get; set; }
}
[Dependent(DependentOnMethod = "OtherMethod", DependentOnVersion = "1")]
public static void FirstMethod()
{
}
[Version("1")]
public static void OtherMethod()
{
}
And the test that asserts the version numbers:
[Test]
public void TestVersions()
{
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
foreach (var method in type.GetMethods())
{
foreach (var customAttribute in method.GetCustomAttributes())
{
var dependent = customAttribute as DependentAttribute;
if (dependent != null)
{
var methodInfo = type.GetMethod(dependent.DependentOnMethod);
Assert.That(methodInfo, Is.Not.Null, "Dependent method not found");
VersionAttribute version = methodInfo.GetCustomAttributes().OfType<VersionAttribute>().FirstOrDefault();
Assert.That(version, Is.Not.Null, "No version attribute on dependent method");
Assert.That(dependent.DependentOnVersion, Is.EqualTo(version.Version));
}
}
}
}
}
thus, if you update one of your methods you would need to update the version number of either the Version attribute or the Dependent attribute. Hopefully better than nothing.
You may change your design :
public abstract class BaseClass
{
protected abstract void A();
}
public class BaseClassEx
{
protected sealed override void A()
{
// action Calling B
}
protected virtual void B()
{
// a default action called second
}
}
In the case of Equals (actually both Equals overloads, concrete type and object) and GetHashCode, Resharper includes a rule that shows a warning in its IntelliSense whenever you forget to implement one of these.
You could enforce it in your code with a runtime check in the constructor of the base class:
public class Base
{
public Base()
{
var baseA = typeof (Base).GetRuntimeMethod("MethodA", new Type[0]);
var baseB = typeof (Base).GetRuntimeMethod("MethodB", new Type[0]);
var derivedA = GetType().GetRuntimeMethod("MethodA", new Type[0]);
var derivedB = GetType().GetRuntimeMethod("MethodB", new Type[0]);
if (baseA.DeclaringType == derivedA.DeclaringType ^
baseB.DeclaringType == derivedB.DeclaringType)
throw new InvalidOperationException("You must override MethodA and MethodB together.");
}
public virtual string MethodA() { return "Hello"; }
public virtual int MethodB() { return 123; }
}
Related
Simple hierarchy, 3 levels and with a shared/single dependency to a class with overloaded methods that differ only by type signature:
When viewed in a debugger, the type of 'this' in Derived.Bar is the instantiated/concrete Double-Derived.
The below works as expected ONLY because of the (dynamic) cast. Remove it and you'll see that the overload resolution uses the calling class rather than the concrete class.
Curious if there's a 'purer' way of it working as expected without the performance hit of DLR (or some other reflection-based alternative):
public class PolymorphicConsumer
{
public void Foo(Base caller)
{
Console.WriteLine("Its all about the base.");
}
public void Foo(Derived caller)
{
Console.WriteLine("Its all about the Derived.");
}
public void Foo(DoubleDerived caller)
{
Console.WriteLine("Its all about the Double-Derived.");
}
}
public abstract class Base
{
protected PolymorphicConsumer _dep;
public Base (PolymorphicConsumer dep)
{
_dep = dep;
}
public virtual void Bar()
{
// No impl.
}
}
public class Derived : Base
{
public Derived(PolymorphicConsumer dep):base(dep)
{ }
public override void Bar()
{
_dep.Foo((dynamic)this);
}
}
public class DoubleDerived : Derived
{
public DoubleDerived(PolymorphicConsumer dep):base(dep)
{ }
}
class Program
{
static void Main(string[] args)
{
var dd = new DoubleDerived(new PolymorphicConsumer());
dd.Bar();
Console.ReadKey();
}
}
Is it possible to do the following specialization in C#? I can do this in C++ but do not understand how to achieve the same result in C#.
class GenericPrinter<T>
{
public void Print()
{
Console.WriteLine("Unspecialized method");
}
}
class GenericPrinter<int>
{
public void Print()
{
Console.WriteLine("Specialized with int");
}
}
Added:
The problem with suggested GenericPrinterInt solution is that I need to explicitly create it. new GenericPrinter<int> will still print Unspecialized method.
What I want is to use this GenericPrinter from another generic class without the knoledge is T equal to int or something else.
I guess the closer you could get in C# would be:
class GenericPrinter<T>
{
public virtual void Print()
{
Console.WriteLine("Unspecialized method");
}
}
class IntPrinter : GenericPrinter<int>
{
public override void Print()
{
Console.WriteLine("Specialized with int");
}
}
Otherwise, the answer is, you can't specialize in C#.
As Lyubomyr Shaydariv said in his comment:
C++ templates are not .NET generics. You can't.
From your edit I guess you will have some type checking to make.
You can do this with a dictionary for example.
class GenericPrinter<T>
{
private Dictionary<Type, Action> _actions
= new Dictionary<Type, Action>()
{
{ typeof(int), PrintInt }
};
public virtual void Print()
{
foreach (var pair in _actions)
if (pair.First == typeof(T))
{
pair.Second();
return ;
}
Console.WriteLine("Unspecialized method");
}
public virtual void PrintInt()
{
Console.WriteLine("Specialized with int");
}
}
Like you can see, you will have to make a method for each type, you want to handle. And you may also encounter some issues when you will try to manipulate T as int. Since, T is really generic (it hasn't any constraint), it will more likely act as an object in your code (not at runtime) you will have to cast it like that (int)(object)yourTVariable in your methods where you are sure that T is an int.
But for this part, I guess some of my peers, will have a better answer than me to give to you.
If it's just about displaying which type you are using:
public virtual void Print()
{
Console.WriteLine($"Specialized with {typeof(T).Name}");
}
But you won't have the unspecialized message anymore (and if you think about it, you can't have a GenericPrinter instantiated without specifying its type. Then it makes no sense to have a method that displays "unspecialized", you will always have a specified type)
Anyway, the answer is still the same, you can't specialize a generic in C#.
It isn't possible in C#.
You can use inheritance instead:
class GenericPrinter<T>
{
public virtual void Print()
{
Console.WriteLine("Unspecialized method");
}
}
class GenericPrinterInt : GenericPrinter<int>
{
public override void Print()
{
Console.WriteLine("Specialized with int");
}
}
According to the updated question, I can only suggest you the following approach. You could create a static factory method in which you can check the type of T and instantiate an appropriate specialized class if the type matches the criteria:
class GenericPrinter<T>
{
public static GenericPrinter<T> Create()
{
if (typeof(int).IsAssignableFrom(typeof(T)))
return (GenericPrinter<T>)(object)new GenericPrinterInt();
if (typeof(double).IsAssignableFrom(typeof(T)))
return (GenericPrinter<T>)(object)new GenericPrinterDouble();
// Other types to check ...
return new GenericPrinter<T>();
}
public virtual void Print()
{
Console.WriteLine("Unspecialized method");
}
}
class GenericPrinterInt : GenericPrinter<int>
{
public override void Print()
{
Console.WriteLine("Specialized with int");
}
}
class GenericPrinterDouble : GenericPrinter<double>
{
public override void Print()
{
Console.WriteLine("Specialized with double");
}
}
Some other generic class:
class SomeGenericClass<T>
{
public readonly GenericPrinter<T> Printer = GenericPrinter<T>.Create();
}
Usage sample:
var intClass = new SomeGenericClass<int>();
intClass.Printer.Print();
// Output: Specialized with int
var doubleClass = new SomeGenericClass<double>();
doubleClass.Printer.Print();
// Output: Specialized with double
var stringClass = new SomeGenericClass<string>();
stringClass.Printer.Print();
// Output: Unspecialized method
You can do it but you need to move your code into lambda expressions
or some flavor of lambdas.
It's not pretty but is fast ( no lookups ) and has the specialization.
You can tailor this to your needs
Cummon Microsoft we shouldn't have to do this.
How many improvements to .Net and no specialization.
public class GenericPrinter<T>
{
public static GenericPrint()
{
T thing = default(T)
switch(thing)
{
case int ival:
_Print = ()=>
{
Console.WriteLine("Specialized Int print Code");
};
break;
default:
_Print = ()=>
{
Console.WriteLine("Some generic print code");
};
break;
}
}
// will be unique for every type of T
public static Action _Print=null;
public void Print()
{
_Print();
}
}
Use would be the same
var printer = new GenericPrinter<int>();
printer.Print();
I have sample object model as below.
[AttributeUsage(AttributeTargets.Method)]
public sealed class CandidateApiForMenuItem : Attribute
{
public CandidateApiForMenuItem(string caption)
{
this.Caption = caption;
}
public string Caption { get; set; }
}
public class FormDataElementBase
{
public FormDataElementBase()
{
}
[CandidateApiForMenuItem("Add PanelGroup")]
public void AddPanelGroup()
{
///...
}
[CandidateApiForMenuItem("Add BoxGroup")]
public void AddBoxGroup()
{
///...
}
[CandidateApiForMenuItem("Remove")]
public void Remove()
{
///...
}
public void GenerateGroupPopupMenuItems()
{
foreach (MethodInfo methodInfo in this.GetType().GetMethods())
{
if (methodInfo.GetCustomAttribute(typeof(CandidateApiForMenuItem)) != null)
{
// This is true both for FormDataElementBase and all derived
// but I want to hide Remove method inside MainGroup class
// However it is displayed again
};
};
}
}
public class BoxGroup : FormDataElementBase
{
}
public class PanelGroup : FormDataElementBase
{
}
public class MainGroup : FormDataElementBase
{
private void Remove()
{
}
}
When user right click, application will display PopupMenu (GenerateGroupPopupMenuItems method). Items of menu will be based on methods who has CandidateApiForMenuItem declared. However, there are derived class (MainGroup) where some methods (f.e: Remove) should not be displayed. What I did, inside MainGroup declared Remove method as private. However, it is displayed again.
Could you pls let me know what I am doing worng here?
Thanks.
First of all, this.GetType().GetMethods() without parameters returns only public instance (i.e. non-static) methods. So MainGroup.Remove won't be returned by this call.
If you make MainGroup.Remove public, this.GetType().GetMethods() will return both methods - for base class and for derived one. Not what you want, I suppose.
If you make FormDataElementBase.Remove virtual and MainGroup.Remove override, GetMethods will return only one Remove method (with DeclaringType==typeof(MainGroup)) - this is better.
And finally, I'd suggest to introduce one more attribute, say, CandidateApiIgnore. If we mark an overridden method with this attribute and modify in the following way GenerateGroupPopupMenuItems method, the stuff should work:
[AttributeUsage(AttributeTargets.Method)]
public sealed class CandidateApiIgnore : Attribute
{
public CandidateApiIgnore() { }
}
public class FormDataElementBase
{
///...
[CandidateApiForMenuItem("Remove")]
public virtual void Remove()
{
///...
}
public void GenerateGroupPopupMenuItems()
{
foreach (MethodInfo methodInfo in this.GetType().GetMethods())
{
if (methodInfo.GetCustomAttribute(typeof(CandidateApiForMenuItem)) != null &&
methodInfo.GetCustomAttribute(typeof(CandidateApiIgnore)) == null)
{
// If a method is overridden and marked with
// CandidateApiIgnore attribute in a derived
// class, it won't be processed here.
};
};
}
public class MainGroup : FormDataElementBase
{
[CandidateApiIgnore]
public override void Remove()
{
throw new NotSupportedException();
}
}
I wrote C# code as described below that inherits a class from a generic class with static methods. I want to call the child class for its static methods (inherited from the base class) without having to specify the type.
EDITED! More "real" code
public class Rec
{
public string Name { get; set; }
public override string ToString() { return this.Name; }
public virtual void Load() { /* HERE IT READS A TEXT FILE AND LOAD THE NAME */ }
}
public class BaseClass<T> : Rec
{
public T Argument { get; set; }
public override void Load() { /* NOW IT LOADS ALSO THE ARGUMENT */ }
public static H Method<H>() where H : Rec, new()
{
H iH = new H();
iH.Load();
iH.Name += " " + iH.Argument.ToString();
return iH;
}
}
public class Child : BaseClass<string> { }
public class SomeOtherClass
{
public void Test()
{
Child i = Child.Method();
//instead of Child.Method<Child>();
}
}
So, instead of having to call method<h>() i'd like to just call method(), so the code should assume that "h" is the caller type. Like in:
How can I do it?
Static methods are not inherited in C#
See this answer for an idea of a potential implementation: Stack Overflow whats-the-correct-alternative-to-static-method-inheritance
You could change method<h> to method and make it an instance method:
public class BaseClass<T> where T, new()
{
public T method() { /* RETURN SOMETHING */ }
}
And then call it as follows:
public class ABC : Child
{
public void Test()
{
var iABC = this.method();
}
}
I just have one basic question :
public class virtualTest
{
public virtual void vTest()
{
Console.WriteLine("Base Class");
}
}
public class derivedVirtualTest : virtualTest
{
public override void vTest()
{
Console.WriteLine("Derived Class");
}
}
Here i have used function overriding with function vTest()
But if i :
public class virtualTest
{
public void vTest()
{
Console.WriteLine("Base Class");
}
}
public class derivedVirtualTest : virtualTest
{
public void vTest()
{
Console.WriteLine("Derived Class");
}
}
removes virtual and override keywords from respective places , then also code works.
How can this be possible?
Or then what is the use of override and virtual (entire function overriding) if code works fine without virtual and override???
EDIt:
My Method through which i am calling above classes
static void Main(string[] args)
{
derivedVirtualTest objderivedVirtualTest = new derivedVirtualTest();
objderivedVirtualTest.vTest();
virtualTest objvirtualTest = new virtualTest();
objvirtualTest.vTest();
Console.ReadLine();
}
As qwr explained, the main difference in terms of OOP is polymorphism. It means that if you access the class which overrides the base member through a base type reference, the call you perform to the overriddable member is redirected to the override.
In case of a class which shadows/hides the base member, the call is not redirected, and the base class' method is being executed.
So, given:
class Base
{
public virtual void OverrideMe()
{
Console.WriteLine("I'm the base");
}
}
class Derived : Base
{
public override void OverrideMe()
{
Console.WriteLine("I'm derived");
}
}
class Shadowing : Base
{
public void OverrideMe()
{
Console.WriteLine("I'm shadowing");
}
}
And using them this way:
var instances = new Base[] {new Base(), new Derived(), new Shadowing()};
foreach (var instance in instances)
{
instance.OverrideMe();
}
Will produce:
I'm the base
I'm derived
I'm the base
Additional difference is that in case of overriding you can evolve your base class, like changing the signature of the base member or removing it completely, without changing the hiding one. Which in some cases may suit needs exactly and in some - not so much.
In case of overriding you must change the signature of overriding member as well, otherwise your code will fail to compile.
In the second example, maybe you test your code like this:
derivedVirtualTest deviTest = new derivedVirtualTest();
deviTest.vTest(); //Result "Derived Class"
Try this, and you'll see that the function has't been overridden yet:
virtualTest deviTest = new derivedVirtualTest();
deviTest.vTest(); //Result "Base Class"
//This will result "Dervived class" in the first one
It will be needed when your sealed method overriding a method
public class Animal{
public virtual void eat() { Console.WriteLine("eating..."); }
public virtual void run() { Console.WriteLine("running..."); }
}
public class Dog: Animal
{
public override void eat() { Console.WriteLine("eating bread..."); }
public sealed override void run() { //If you skipped override here it will throws an error
Console.WriteLine("running very fast...");
}
}
public class TestSealed
{
public static void Main()
{
BabyDog d = new BabyDog();
d.eat();
d.run();
}
}