C# Use Generic Type in Interface

Use Generic Type in Interface.  Receiving error:  Type or namespace 'T' could not be found (are you missing an assembly or reference).  I want a generic return type as I can pass different models to the select statement.  Any ideas?
 public interface ISQL
    {
        Boolean InsertStatement(string sqlString);
        Boolean UpdateStatement(string sqlString); 
        Boolean DeleteStatement(string sqlString);
        List<T> SelectStatement(string sqlString); 
    }

Open in new window

LVL 2
CipherISAsked:
Who is Participating?
 
Dirk StraussSenior Full Stack DeveloperCommented:
Try

public interface ISQL<T>
{
    Boolean InsertStatement(string sqlString);
    Boolean UpdateStatement(string sqlString); 
    Boolean DeleteStatement(string sqlString);
    List<T> SelectStatement(string sqlString); 
}

Open in new window

0
 
MishaProgrammerCommented:
Try to add a generic constrain to the interface:

public interface ISQL<T>
    {
        Boolean InsertStatement(string sqlString);
        Boolean UpdateStatement(string sqlString); 
        Boolean DeleteStatement(string sqlString);
        List<T> SelectStatement(string sqlString); 
    }

Open in new window

0
 
CipherISAuthor Commented:
What is the difference between the recommended solutions above and what I have below?
    public interface ISQL
    {
        Boolean InsertStatement(string sqlString);
        Boolean UpdateStatement(string sqlString); 
        Boolean DeleteStatement(string sqlString);
        List<T> SelectStatement<T>(string sqlString); 
    }

Open in new window

0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

 
MishaProgrammerCommented:
You should add a generic constrain to the interface.

public interface ISQL<T>

Open in new window

0
 
CipherISAuthor Commented:
@Misha - why?
0
 
MishaProgrammerCommented:
ToCollection<T>, otherwise the compiler doesn't understand where this T is coming from. Do you try this code? Does it work? or not?
0
 
Dirk StraussSenior Full Stack DeveloperCommented:
The code that we suggested is correct and solves your problem. Have a look at this article for further reading. Also read https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/generic-interfaces
0
 
CipherISAuthor Commented:
So, I'm trying to implement the Interface in the class and it is giving me problems with the <T>.  I want to pass in a property and not define the property in the class.  When I use the class I will pass the property.  

Getting the same error in the class.
    public interface ISQL<T>
    {
        Boolean InsertStatement(string sqlString);
        Boolean UpdateStatement(string sqlString); 
        Boolean DeleteStatement(string sqlString);
        List<T> SelectStatement(string sqlString); 
    }

Open in new window

    public class SQLData : ISQL<T>
    {
        SqlConnection SQLConn = new SqlConnection();
        SqlCommand SQLCmd = new SqlCommand();
        string strConnection = string.Empty;

        #region ISQL<T> Members

        public bool InsertStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool UpdateStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool DeleteStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public List<T> SelectStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        #endregion

Open in new window

0
 
CipherISAuthor Commented:
Looks like below is the solution.  Testing.
    public class SQLData<T> : ISQL<T>
    {
        
        SqlConnection SQLConn = new SqlConnection();
        SqlCommand SQLCmd = new SqlCommand();
        string strConnection = string.Empty;


        #region ISQL<T> Members

        public bool InsertStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool UpdateStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool DeleteStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public List<T> SelectStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

Open in new window

0
 
CipherISAuthor Commented:
Having issues implementing the generic.
namespace App.Patterns.Repository
{
    public interface ISQL<T>
    {
        Boolean InsertStatement(string sqlString);
        Boolean UpdateStatement(string sqlString); 
        Boolean DeleteStatement(string sqlString);
        List<T> SelectStatement(string sqlString);
        List<T> SelectSPROC(string sqlString);
    }
}

Open in new window

namespace App.Patterns.Repository
{
    public class SQLData : ISQL<T>  //Error here.  Same error as mentioned above.
    {
        SqlConnection SQLConn;
        SqlCommand SQLCmd;
        SqlDataReader SQLRdr;
        string strConnection = string.Empty;

        #region ISQL<T> Members

        public bool InsertStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool UpdateStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool DeleteStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public List<T> SelectStatement(string sqlString) //Error here.  Same error as mentioned above.
        {
            throw new NotImplementedException();
        }

        public List<T> SelectSPROC<T>(string sprocName) where T:new()
        {
            List<T> result = new List<T>();

            try
            {
                using (SQLConn = new SqlConnection("Your Connection String"))
                using (SQLCmd = new SqlCommand())
                {

                    SQLCmd.CommandText = sprocName;
                    SQLCmd.CommandType = CommandType.StoredProcedure;
                    SQLCmd.Connection = SQLConn;

                    SQLConn.Open();

                    SQLRdr = SQLCmd.ExecuteReader();

                    while (SQLRdr.Read())
                    {
                        T t = new T();

                        for (int inc = 0; inc < SQLRdr.FieldCount; inc++)
                        {
                            Type type = t.GetType();
                            PropertyInfo prop = type.GetProperty(SQLRdr.GetName(inc));
                            prop.SetValue(t, SQLRdr.GetValue(inc), null);
                        }

                        result.Add(t);
                    }
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                SQLRdr.Close();
                SQLConn.Close();
                SQLCmd.Dispose();
            }

            return result;
        }

        #endregion
    }
}

Open in new window

0
 
käµfm³d 👽Commented:
You'd have to make SqlData be generic too:

public class SQLData<T> : ISQL<T>

Open in new window

2
 
CipherISAuthor Commented:
Still having problems.  I don't know if this is the correct way to code this.  This is what I'm trying to accomplish.  I want to pass the SQL to return the correct data per datamodel.  Below are two example models.  I am attempting to use the Repository Pattern to call the correct SPROC which will return the appropriate data per model which is why I'm trying to use Generics.  I am having problems implementing it.  Can it be implemented?  Is there a better way?  Am I over thinking this?  I've indicated the errors below in public List<T> SelectSPROC(string sprocName) method.
public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

public class Company
{
    public string Name { get; set; }
    public string Contact { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

Open in new window

    public interface ISQL<T>
    {
        Boolean InsertStatement(string sqlString);
        Boolean UpdateStatement(string sqlString); 
        Boolean DeleteStatement(string sqlString);
        List<T> SelectStatement(string sqlString);
        List<T> SelectSPROC(string sprocName);
    }

Open in new window

public class SQLData<T> : ISQL<T>
    {
        SqlConnection SQLConn;
        SqlCommand SQLCmd;
        SqlDataReader SQLRdr;
        string strConnection = string.Empty;

        #region ISQL<T> Members

        public bool InsertStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool UpdateStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public bool DeleteStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public List<T> SelectStatement(string sqlString)
        {
            throw new NotImplementedException();
        }

        public List<T> SelectSPROC(string sprocName) where T:new()  //HERE I RECEIVE ERROR - CONSTRAINTS ARE NOT ALLOWED ON NON-GENERIC DECLARATIONS
        {
            List<T> result = new List<T>();

            try
            {
                using (SQLConn = new SqlConnection("Your Connection String"))
                using (SQLCmd = new SqlCommand())
                {

                    SQLCmd.CommandText = sprocName;
                    SQLCmd.CommandType = CommandType.StoredProcedure;
                    SQLCmd.Connection = SQLConn;

                    SQLConn.Open();

                    SQLRdr = SQLCmd.ExecuteReader();

                    while (SQLRdr.Read())
                    {
                        T t = new T();  //HERE I GET AN ERROR - Cannot create an instance of the variable type 'T' because it does not have the new() constraint

                        for (int inc = 0; inc < SQLRdr.FieldCount; inc++)
                        {
                            Type type = t.GetType();
                            PropertyInfo prop = type.GetProperty(SQLRdr.GetName(inc));
                            prop.SetValue(t, SQLRdr.GetValue(inc), null);
                        }

                        result.Add(t);
                    }
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                SQLRdr.Close();
                SQLConn.Close();
                SQLCmd.Dispose();
            }

            return result;
        }

        #endregion

Open in new window

0
 
käµfm³d 👽Commented:
You get an error on that line because the runtime can't know that T is new-able unless you tell it. You need to add a type constraint to your definition:

public class SQLData<T> : ISQL<T>
    where  T: new()

Open in new window


https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters
1
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.