【问题标题】:What is a base class constructor and why would I want to use it? (with Example)什么是基类构造函数,我为什么要使用它? (带示例)
【发布时间】:2016-08-11 18:26:40
【问题描述】:

我目前正在开发一个 ASP.NET Core MVC 应用程序(我正在将一个项目从 .NET 迁移到 .NET Core)并且我想知道基本构造函数。

具体来说,代码如下:

public partial class CompanyFormsContext : DbContext
{
    public CompanyFormsContext()
        : base("name=CompanyFormsContext")
    {
    }

    public CompanyFormsContext(string connName)
        : base("name=" + connName)
    {
    }
...
}

这是一种 ASP.NET 语法,现在 DbContext 不接受字符串作为参数,而是接受 DbContextOptionsBuilder。

我的问题是:基类构造函数如何以及何时有用?在这里我可以为 CompanyFormsContext 设置一个空的构造函数,但我仍然可以为基类构造函数传递一个参数?

我猜测基本构造函数与 DbContext 相关,因为 CompanyFormsContext 是一个子类。但是,我对为什么要在这里使用基类感到困惑。

以下是我们在项目中调用这些方法的两种方式:

        //First
        var db = new CompanyFormsContext(siteUrl.StartsWith("http://www.") ? "CompanyFormsContext" : "CompanyFormsContextQA");
        //Second
        var env = Request.Headers["environment"].First();
        var db = new CompanyFormsContext(env);

我可能不得不修改它们以使其能够与新的 .NET Core 语法一起使用。每个实例会调用哪个构造函数?

简而言之,我想了解在这种情况下如何使用基类以及它们的一般用途是什么。谢谢

【问题讨论】:

    标签: c# asp.net .net asp.net-mvc entity-framework


    【解决方案1】:

    如果有在许多不同场景中使用的某种初始化,则使用基类构造函数。例如,如果你有类似的东西

    public bool Abc { get; set; }
    
    private readonly string x;
    
    private readonly string newName;
    
    public Test(string x, string newName)
    {
       Abc = true;
       thix.x = x;
       this.newName = newName;
    }
    

    (是的,非常愚蠢的示例,但无论如何)并且您总是希望初始化发生,您可能不希望每次有一个新的派生类时都一遍又一遍地键入它。这不仅很烦人,而且从维护的角度来看也很糟糕;如果您出于某种原因必须更改逻辑,则必须前往输入它的每个地方并更改它,如果您不小心错过了某个地方,则会将错误引入系统。

    请注意,父类型和派生类型都可能有多个构造函数。例如:

    public abstract class SomeClass
    {
        public SomeClass(string a, string b)
        {
           // ...
        }
    
        public SomeClass()
        {
          //...
        }
    }
    
    public SomeDerivedType : SomeClass
    {
         public SomeDerivedType(string a, string b) : base(a, b)
         {
             // ...
         }
    
         public SomeDerivedType() : base("test", "string")
         {
            // ..
         }
    }
    

    基构造函数和派生类型构造函数具有不同的参数是完全有效的。如果您考虑一下,那是有道理的;您正在调用一个完全不同的构造函数。例如,执行以下操作是完全有效的:

    public SomeDerivedType()...
    {
       // The CollectionType constructor has a different number of parameters than SomeDerivedType does
       abc = new CollectionType<int>(1, 2, 3, 4, 5);
    }
    

    【讨论】:

      【解决方案2】:

      去MSDN看看https://msdn.microsoft.com/en-us/library/ms173115.aspx

      在派生类中,如果未使用 base 关键字显式调用基类构造函数,则隐式调用默认构造函数(如果有)。这意味着以下构造函数声明实际上是相同的:

      ...

      如果基类不提供默认构造函数,则派生类必须使用 base 显式调用基构造函数。 构造函数可以使用 this 关键字调用同一对象中的另一个构造函数。与 base 一样,this 可以带或不带参数使用,构造函数中的任何参数都可以用作 this 的参数,或用作表达式的一部分。例如,上例中的第二个构造函数可以这样改写:

      【讨论】:

        【解决方案3】:

        你用字符串参数调用你的构造函数。所以接受字符串的那个被执行。你的基类的构造函数也因为:base()而被执行。

        如果您想在该构造函数中执行代码,您通常会使用基本构造函数。并且您不能或不想将该代码复制到您的子构造函数。除非您不希望执行基本构造函数代码,否则总是如此。您通过不使用 base () 来覆盖它

        【讨论】:

          【解决方案4】:

          来自https://msdn.microsoft.com/en-us/library/hfw7t1ce.aspx

          public class BaseClass
          {
              int num;
          
              public BaseClass()
              {
                  Console.WriteLine("in BaseClass()");
              }
          
              public BaseClass(int i)
              {
                  num = i;
                  Console.WriteLine("in BaseClass(int i)");
              }
          
              public int GetNum()
              {
                  return num;
              }
          }
          
          public class DerivedClass : BaseClass
          {
              // This constructor will call BaseClass.BaseClass()
              public DerivedClass() : base()
              {
              }
          
              // This constructor will call BaseClass.BaseClass(int i)
              public DerivedClass(int i) : base(i)
              {
              }
          
              static void Main()
              {
                  DerivedClass md = new DerivedClass();
                  DerivedClass md1 = new DerivedClass(1);
              }
          }
          /*
          Output:
          in BaseClass()
          in BaseClass(int i)
          */
          

          在这里我意识到,在 DerivedClass 中没有任何信息,就会调用 BaseClass 构造函数。因此,对于我的问题:

          public partial class CompanyFormsContext : DbContext
          {
              public CompanyFormsContext()
                  : base("name=CompanyFormsContext")
              {
              }
          
              public CompanyFormsContext(string connName)
                  : base("name=" + connName)
              {
              }
          ...
          }
          

          在这两种情况下都会调用 DbContext(string),但在一种情况下输入参数是 "name=CompanyFormsContext",在另一种情况下是 "name=" + connName

          因此,为了能够使用 .NET Core 语法更改为 DbContextOptionsBuilder 参数,我可以定义两个 OptionsBuilders 实例,然后根据 CompanyFormsContext 的输入在基础构造函数中调用它们。

          我相信这就是我一直在寻找的东西,并且由于其他答案,我能够做到这一点。完成后我会改进我的答案并分享完整的代码。

          【讨论】:

            猜你喜欢
            • 2011-02-24
            • 2017-12-18
            • 1970-01-01
            • 2017-11-09
            • 2014-06-23
            • 1970-01-01
            • 2020-03-17
            • 2010-09-12
            相关资源
            最近更新 更多