Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to implement VB interface in C# because of constraints error

I can't figure this out and I don't know why. Sorry is this bad question, I have the following interface in 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

When I implement the interface in C# I get the following error.

The constraints for type parameter 'T' of method ExecuteSQL(string, bool, params System.Data.SqlClient.SqlParameter[]) must match the constraints for type parameter 'T' of interface method IFoo.ExecuteSQL(string, bool, params System.Data.SqlClient.SqlParameter[])'. Consider using an explicit interface implementation instead

This is the C# implemenation of the interface. Not sure why I get that error when I use:

where T : struct

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

enter image description here

like image 306
Son_of_Sam Avatar asked Dec 15 '15 15:12

Son_of_Sam


Video Answer


1 Answers

The VB and C# compilers generate different IL when constraining the generic type parameter to value types (note the additional .ctor ([mscorlib]System.ValueType constraint that the C# compiler generates).

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

The different method signatures result in the mismatch that is indicated by the error message.

I think to have the VB compiler generate something similar you would have to add a New constraint as well - which is not allowed by the compiler. Consequently, as far as I see, there is no way around explicitly implementing that interface.

(I checked this using the C# 5 compiler, not using the new Roslyn compiler of VS 2015 which might behave differently)

Update

As pointed out by @Luisgrs the new Roslyn VB compiler included with VS 2015 now generates the generic constraint the same way as the C# compiler does. So one solution would be to update your compiler / Visual Studio version.

like image 92
Dirk Vollmar Avatar answered Sep 21 '22 10:09

Dirk Vollmar