【问题标题】:Unable to implement VB interface in C# because of constraints error由于约束错误,无法在 C# 中实现 VB 接口
【发布时间】:2015-12-15 15:15:51
【问题描述】:

我无法弄清楚,也不知道为什么。对不起这个问题不好,我在VB中有以下界面

Public Interface IFoo  

    Sub ExecuteSQL(sql As String, ParamArray parameters() As SqlParameter)
    Sub ExecuteSQL(sql As String, useTransaction As Boolean, ParamArray parameters() As SqlParameter)
    Function ExecuteSQLAsync(sql As String, ParamArray parameters() As SqlParameter) As Task
    Function ExecuteSQLAsync(sql As String, useTransaction As Boolean, ParamArray parameters() As SqlParameter) As Task
    Function ExecuteSQL(Of T As Structure)(sql As String, ParamArray parameters() As SqlParameter) As T
    Function ExecuteSQL(Of T As Structure)(sql As String, useTransaction As Boolean, ParamArray parameters() As SqlParameter) As T
    Function ExecuteSQLAsync(Of T As Structure)(sql As String, ParamArray parameters() As SqlParameter) As Task(Of T)
    Function ExecuteSQLAsync(Of T As Structure)(sql As String, useTransaction As Boolean, ParamArray parameters() As SqlParameter) As Task(Of T)

End Interface

当我在 C# 中实现接口时,出现以下错误。

方法 ExecuteSQL(string, bool, params System.Data.SqlClient.SqlParameter[]) 的类型参数 'T' 的约束必须匹配接口方法 IFoo.ExecuteSQL(string, bool 的类型参数 'T' 的约束, 参数 System.Data.SqlClient.SqlParameter[])'。考虑改用显式接口实现

这是接口的 C# 实现。不知道为什么我在使用时会收到该错误:

其中 T : 结构

public class Foo : IFoo
{
    public T ExecuteSQL<T>(string sql, bool useTransaction, params System.Data.SqlClient.SqlParameter[] parameters) where T : struct
    {
        throw new NotImplementedException();
    }

    public T ExecuteSQL<T>(string sql, params System.Data.SqlClient.SqlParameter[] parameters) where T : struct
    {
        throw new NotImplementedException();
    }

    public void ExecuteSQL(string sql, bool useTransaction, params System.Data.SqlClient.SqlParameter[] parameters)
    {
        throw new NotImplementedException();
    }

    public void ExecuteSQL(string sql, params System.Data.SqlClient.SqlParameter[] parameters)
    {
        throw new NotImplementedException();
    }

    public Task<T> ExecuteSQLAsync<T>(string sql, bool useTransaction, params System.Data.SqlClient.SqlParameter[] parameters) where T : struct
    {
        throw new NotImplementedException();
    }

    public Task<T> ExecuteSQLAsync<T>(string sql, params System.Data.SqlClient.SqlParameter[] parameters) where T : struct
    {
        throw new NotImplementedException();
    }

    public Task ExecuteSQLAsync(string sql, bool useTransaction, params System.Data.SqlClient.SqlParameter[] parameters)
    {
        throw new NotImplementedException();
    }

    public Task ExecuteSQLAsync(string sql, params System.Data.SqlClient.SqlParameter[] parameters)
    {
        throw new NotImplementedException();
    }
}

【问题讨论】:

  • 这看起来很奇怪。显式实现编译虽然 - T IFoo.ExecuteSQL&lt;T&gt;(string sql, params SqlParameter[] parameters)
  • 我刚试过这个,效果很好,我想我们一定错过了其他东西。
  • @stuartd 我明白这一点,但为什么我需要对泛型方法进行隐式实现。我有其他不通用的方法,我能够毫无问题地实现接口。另外,如果我在没有限制的情况下从 ExecuteSQL(Of T) 更改方法,则没有问题
  • @DavidG 好主意,让我隔离问题。
  • 顺便说一句,您更新的代码仍然适用于我。

标签: c# vb.net visual-studio visual-studio-2013


【解决方案1】:

VB 和 C# 编译器在将泛型类型参数约束为值类型时生成不同的 IL(注意 C# 编译器生成的附加 .ctor ([mscorlib]System.ValueType 约束)。

VB:

instance !!T ExecuteSQL<valuetype T>(string sql,
              bool useTransaction,
              class [System.Data]System.Data.SqlClient.SqlParameter[] parameters) cil managed

C#:

instance !!T ExecuteSQL<valuetype .ctor ([mscorlib]System.ValueType) T>(string sql,
              bool useTransaction,
              class [System.Data]System.Data.SqlClient.SqlParameter[] parameters) cil managed

不同的方法签名导致错误消息指示的不匹配。

我认为要让 VB 编译器生成类似的东西,您还必须添加一个 New 约束 - 这是编译器不允许的。因此,据我所知,没有办法明确实现该接口。

(我使用 C# 5 编译器检查了这一点,而不是使用 VS 2015 的新 Roslyn 编译器,它的行为可能会有所不同)

更新

正如@Luisgrs 所指出的,VS 2015 中包含的新 Roslyn VB 编译器现在生成通用约束的方式与 C# 编译器相同。因此,一种解决方案是更新您的编译器/Visual Studio 版本。

【讨论】:

  • 啊,这很有趣 - 当 Resharper 在问题中自动实现 VB 接口时,它会添加 Of T As {Structure, ValueType}) - 这不会编译。
  • 我不明白为什么 C# 编译器会在 T 是`struct 时添加 ctor ([mscorlib]System.ValueType)
  • 那为什么他的代码对我来说可以正常工作呢?我很困惑!
  • 在 vs2015 中他们使用 Rosalyn 编译器,在 2013 年他们使用旧编译器,如果您在 vs2013 中打开解决方案,它将中断。
  • 在 VS2015 VB 代码现在像 C# 一样编译:instance !!T ExecuteSQL&lt;valuetype .ctor ([mscorlib]System.ValueType) T&gt;...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-11
相关资源
最近更新 更多