在 C# 中继承 Visual Basic 类并重写采用可选参数的构造函数
设置
我们的大部分代码库都在 VB.NET 中。我正在用 C# 开发一个项目,该项目使用了 VB.NET 代码中的大量程序集。
VB.NET 中有三个相关的类:
Public MustInherit Class mdTable
Public Sub New(ByVal sqlConnectionStr As String, Optional ByVal maxSecsToDisableConnection As Integer = 60)
ReDim pConnStr(0)
pConnStr(0) = sqlConnectionStr
pDBName = parseDBName(sqlConnectionStr)
m_colLastConnectStatus.disablePeriod = maxSecsToDisableConnection
End Sub
Public MustInherit Class xsTable //uses the constructor above since second parameter is optional
Inherits mdTable
Public Sub New(ByVal sqlConnectionString As String)
MyBase.New(sqlConnectionString)
End Sub
Public Class SharedCallsTable //the only constructor available in this class
Inherits xsTable
Public Sub New(Optional ByRef lErrStr As String = "", _
Optional ByVal checkTableExists As Boolean = False, _
Optional ByVal sqlServerIndex As Integer = -1)
MyBase.New(forceServerIndex:=sqlServerIndex)
defineTable(DBUser, checkTableExists)
lErrStr &= CStr(IIf(errStr <> "", vbCrLf & errStr, ""))
End Sub
显然,所有这些类都在 Visual Basic 中。
有许多不同版本的 SharedCallsTable 可以处理 SQL 数据库中的其他表类型,SharedCallsTable 只是一个示例。
问题:
我无法使用将单个字符串作为构造函数的 xsTable 构造函数创建 SharedCallsTable 的实例,因为它调用具有可选参数 (maxSecsToDisableConnection) 的 mdTable 构造函数。 C# 不支持可选参数。
所以当我这样做时:
SharedCallsTable myTable = new SharedCallsTable(connectionString);
我得到
SharedCallsTable 不包含采用“1”个参数的构造函数
到目前为止的进度
我在 C# 中创建了另一个类 xsToolboxTable,它继承 xsTable 并且只调用单个字符串构造函数,如下所示:
class xsToolboxTable : xsTable
{
public xsToolboxTable(string connectionString) : base(connectionString)
{
}
}
但是,这意味着我只能实例化 xsTable,但不能实例化 SharedCallsTable,因为它们都继承自同一个类。
我还尝试让我的扩展类继承自 SharedCallsTable,但它给了我同样的结果。
我明白了
SharedCallsTable 不包含采用“1”个参数的构造函数
我真正需要做的是调用基类构造函数的基类,即 xsTableExtension 的基类是 SharedCallsTable。 SharedCallsTable 的基础是 xsTable,它具有我需要使用的单个字符串构造函数。
我知道这确实很复杂,可能有一个非常简单的解决方案,但我完全缺少。
这有点复杂,所以请耐心等待。
The Setup
Most of our code base is in VB.NET. I'm developing a project in C# that uses a lot of the assemblies from the VB.NET code.
There are three relevant classes in VB.NET:
Public MustInherit Class mdTable
Public Sub New(ByVal sqlConnectionStr As String, Optional ByVal maxSecsToDisableConnection As Integer = 60)
ReDim pConnStr(0)
pConnStr(0) = sqlConnectionStr
pDBName = parseDBName(sqlConnectionStr)
m_colLastConnectStatus.disablePeriod = maxSecsToDisableConnection
End Sub
Public MustInherit Class xsTable //uses the constructor above since second parameter is optional
Inherits mdTable
Public Sub New(ByVal sqlConnectionString As String)
MyBase.New(sqlConnectionString)
End Sub
Public Class SharedCallsTable //the only constructor available in this class
Inherits xsTable
Public Sub New(Optional ByRef lErrStr As String = "", _
Optional ByVal checkTableExists As Boolean = False, _
Optional ByVal sqlServerIndex As Integer = -1)
MyBase.New(forceServerIndex:=sqlServerIndex)
defineTable(DBUser, checkTableExists)
lErrStr &= CStr(IIf(errStr <> "", vbCrLf & errStr, ""))
End Sub
All of these are in Visual Basic, obviously.
There are many different versions of the SharedCallsTable that deal with other table types in our SQL database, SharedCallsTable is just one example.
The problem:
I can not create an instance of SharedCallsTable by using the xsTable constructor that takes a single string as a constructor, because it calls the mdTable constructor which has an optional parameter(maxSecsToDisableConnection). C# does not support optional parameters.
So when I do this:
SharedCallsTable myTable = new SharedCallsTable(connectionString);
I get
SharedCallsTable does not contain a constructor that takes '1' arguments
Progress so far
I have created another class, xsToolboxTable, in C# that inherits xsTable and just calls the single string constructor like so:
class xsToolboxTable : xsTable
{
public xsToolboxTable(string connectionString) : base(connectionString)
{
}
}
However, this means I can only instantiate an xsTable, but not an instance of SharedCallsTable since they both inherit from the same class.
I have also tried making my extension class inherit from SharedCallsTable, but then it gives me the same.
I get
SharedCallsTable does not contain a constructor that takes '1' arguments
What I really need to do is call the base of the base class constructor, that is, the base of xsTableExtension is SharedCallsTable. The base of SharedCallsTable is xsTable which has the single string constructor that I need to use.
I know this is really convoluted and there may be a really simple solution that I'm just completely missing.
This is kind of complicated, so please bear with me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是否有某种原因不能只传递可选参数的值?例如,
可选参数实际上只是一个编译器技巧,如果您不提供参数的值,编译器会查看默认值并为您提供。因此,通过提供与默认值相同的值,您将观察到与支持可选参数但忽略它们时相同的行为。
编辑:
好吧,从评论来看,我想我误解了你的问题。听起来您要求的是能够使用用户提供的连接字符串创建 SharedCallsTable 的实例,绕过其构造函数逻辑,就好像它有一个直接链接到的构造函数一样基类构造函数。
你不能这样做,而且有充分的理由。构造函数负责使对象处于正确的使用状态,并且您不能简单地绕过该逻辑并期望对象能够工作。
如果您希望能够提供连接字符串,则需要向 SharedCallsTable 添加一个构造函数,该构造函数链接到基类并确保该类处于可使用的合理状态。
Is there some reason you can't just pass values for the optional parameters? e.g.
Optional parameters are really just a compiler trick whereby if you don't supply the value for a parameter the compiler has a look what the default value is and supplies for you. So by supplying values that are the same as the defaults, you'll observe the same behaviour as if optional parameters were supported and you omitted them.
Edit:
OK from the comment I think I misunderstood your question. It sounds like what you're asking for is to be able to create an instance of
SharedCallsTable
with a user-provided connection string, bypassing its constructor logic, as if it had a constructor that chained directly to the base class constructor.You can't do this, and for a good reason. Constructors do the work to get an object in the right state to be used, and you cannot simply bypass that logic an expect an object to work.
If you want to be able to provide a connection string, you'll need to add a constructor to
SharedCallsTable
which chains to the base class and ensures the class is in a reasonable state to be used.不,您不想调用“基类构造函数的基类” - 您希望像平常一样调用基类构造函数,只是显式传递所有参数。基本上,只需将其视为没有任何可选参数的方法即可。对于其他地方的构造函数调用和链接都是如此:
如果您愿意,您可以像这样从类派生:(
不过,不要只是为了调用具有某些默认值的构造函数而从类派生。)
请注意,C# 4.0顺便说一句,确实支持可选参数,所以隧道尽头有光明。
No, you don't want to be calling the "base of the base class constructor" - you want to be calling the base class constructor as normal, just explicitly passing in all arguments. Just treat it as a method which doesn't have any optional parameters, basically. This is true for both the constructor call elsewhere and chaining:
and you can derive from the class like this, if you want to:
(Don't derive from the class just to call the constructor with some defaults though.)
Note that C# 4.0 does support optional parameters btw, so there's light at the end of the tunnel.
当我按照乔恩的建议执行此操作时
,我得到了与以前相同的错误
我的解决方案(供将来参考)是使用不采用可选参数且仅接受连接的构造函数来覆盖祖父类 mdTable 中的构造函数细绳。
直到 C# 4.0 发布。
When I do this as suggested by Jon
I get the same error as before
My solution (for future reference) is to override the constructor in the grandparent class mdTable with one that does not take an optional parameter and just accepts a connection string.
Until C# 4.0 is out that is.