如果覆盖另一个方法,则强制覆盖方法

时间:2015-03-13 09:14:04

标签: c#

如果覆盖了另一个方法,有没有办法强制覆盖虚方法?

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
    }
}

修改

非常感谢Answers。看看如何实现这一点非常有趣,但对于我的明确案例,它并不是非常重要。

另外,我忘了提及如何使用这些方法:(在BaseClass中)

pulbic bool EditEntity(Guid id)
{
    A();

    // Some code that edits Entites

    B();
}

4 个答案:

答案 0 :(得分:0)

也许你不能通过编译错误强制它,但你可以编写一个测试,通过某些属性断言方法是同步的。也可以看出存在一些依赖性。

一个粗略的例子是这样的:

[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()
{
}

断言版本号的测试:

[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));
                }
            }
        }
    }
}

因此,如果您更新了某个方法,则需要更新Version属性或Dependent属性的版本号。希望总比没有好。

答案 1 :(得分:0)

不,你不能。但这让我觉得你怎么能达到同样的理念呢?

我想出的最好的想法是声明一个包含方法包的接口。

 public interface IMyOverridablePackage
 {
     void A_Override();
     void B_Override();
 }

然后为基类提供一个受保护的方法,其中子类可以显式覆盖方法集。

protected void SetOverride(IMyOverridablePackage overridablePackage)
{
    _overridablePackage = overridablePackage;
}

那么这里有两个类,一个是做的,另一个是不覆盖方法集的:

 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");
    }
}

基类的实现:

 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;
     }
 }

这确实达到了目标,但当然你必须问我想要多少钱?&#39;是否值得额外的代码?

这是一个工作的dotnetfiddle: https://dotnetfiddle.net/xmPn20

答案 2 :(得分:0)

您可以更改您的设计:

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
    }
}

答案 3 :(得分:0)

Equals(实际上是Equals重载,具体类型和对象)和GetHashCode的情况下,Resharper包含一个规则,当您忘记实现其中一个时,它会在其IntelliSense中显示警告。

您可以在代码中使用基类的构造函数中的运行时检查来强制执行它:

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; }
}