一个有2种返回类型的方法

本文关键字:2种 返回类型 方法 一个 | 更新日期: 2023-09-27 18:03:29

好的,我有3个类:教师学生数据库。我想从数据库中读取数据,并把它放在TeacherStudent。所以我必须这样写:

public Teacher dbSelect(string Table="Teacher")
{
    Table = char.ToUpper(Table[0]) + Table.Substring(1);
    string query = "SELECT * FROM " + Table + ";";
    return dbConnect(query, true);
}

但我必须有这个确切的方法学生返回:

public Student dbSelect(string Table="Student")
{
    Table = char.ToUpper(Table[0]) + Table.Substring(1);
    string query = "SELECT * FROM " + Table + ";";
    return dbConnect(query, true);
}

现在我可以写每个在他们的ViewModel,但我想把他们在数据库类。有什么办法可以做到吗?
(我知道我可以在列表中返回它们,然后使用该列表,但只是想知道是否有一种方法!)

更新:我忘了把dbConnect放在这里,所以:

public List<Teacher> dbConnect(string query)
    {
        SQLiteConnection conn = null;
        SQLiteCommand command = null;
        SQLiteDataReader reader = null;
        Teacher result = new Teacher(null, null, null, null, null, null, null, null);
            //    try
            {
                conn = new SQLiteConnection(db.db);
                conn.Open();
                command = new SQLiteCommand(query, conn);
                reader = command.ExecuteReader();
            }
            //   catch (Exception ex) { }
            while (reader.Read())
            {
                Teacher temp = new Teacher(
                    reader[0].ToString(),    
                    reader[1].ToString(),                              
                    reader[2].ToString(),                              
                    reader[3].ToString(),                              
                    reader[4].ToString(), 
                    reader[5].ToString(),                              
                    reader[6].ToString(),                              
                    reader[7].ToString()                               
                    );
                result.Items.Add(temp);
            }
        conn.Close();
        return result.Items;
    }

同样,对于Student返回:

public List<Student> dbConnect(string query)
{
    ...
}  

答案:我有一个类,当然想返回一个特定类型的列表,所以我使用@Jauch答案,但是返回列表

一个有2种返回类型的方法

这是一个关于如何做你想做的事情的想法,改编自我的代码:

public class BaseClass<T> 
    where T : new ()
{
    protected List<object> list;
    protected string query;
    protected PropertyInfo[] fProperties;
    protected Assembly fStoreAssembly;
    public BaseClass()
    {
        list = new List<T>();
        fStoreAssembly = Assembly.GetAssembly (typeof(T));
        fProperties = typeof(T).GetProperties();
    }
    public void Read()
    {
        SQLiteConnection conn = null;
        SQLiteCommand command = null;
        SQLiteDataReader reader = null;
        try
        {
            conn = new SQLiteConnection(db.db);
            conn.Open();
            command = new SQLiteCommand(query, conn);
            reader = command.ExecuteReader();
            StoreResults (reader);
            conn.Close();
        }
        catch (Exception ex) 
        {
            //deal with the exception here
        }
    }
    //Store results walks through all the records returned and 
    //creates new instances of the store object and saves in the list,
    //using reflection
    protected void StoreResults (SQLiteDataReader reader)
    {
        if (fProperties == null)
            throw new Exception ("Store type definition is missing");
        while (reader.Read ())
        {                
            object newStoreItem = fStoreAssembly.CreateInstance (typeof(T).FullName);                
            foreach (PropertyInfo pi in fProperties)
            {
                string lcName = pi.Name.ToLower ();
                if (HasColumn(reader, lcName))
                {
                    if (!reader.IsDBNull(reader.GetOrdinal(lcName)))
                        pi.SetValue(newStoreItem, reader[lcName], null);                    
                }
            }
            list.Add (newStoreItem);
        }
    }
    public bool HasColumn (SQLiteDataReader reader, string columnName)
    {
        foreach (DataRow row in reader.GetSchemaTable().Rows)
        {
            if (row ["ColumnName"].ToString () == columnName)
                return true;
        }
        return false;
    }
}

下面是如何创建Teacher和Student

public class TeacherInfo
{
    //Properties for store info from database
}
public class Teacher : BaseClass<TeacherInfo>
{
     public Teacher ()
         : BaseClass()
     {
         query = "whatever you want here"
     }             
}
public class StudentInfo
{
    //Properties for store info from database
}
public class Student : BaseClass<StudentInfo>
{
     public Student ()
         : BaseClass()
     {
         query = "whatever you want here";
     }
}

由于Read例程是公共的,您可以从任何Teacher或Student实例调用Read。您甚至可以创建它们并将其存储为BaseClass,如果您不需要知道它是学生还是教师(用于常见例程等),则可以直接使用它

这不是一个广泛的例子,但只是一个方向的点,您可以使用它来使您的代码更通用。

您可以遵循使用接口返回值的语义,然后将返回类型强制转换为适当的类型,或者使用基类(接口更好,因为在实现接口时仍然可以将其他类扩展为基类)。实体接口可以按如下方式创建,

public interface SchoolEntity { 
    // Provide the similar properties as members of this interface.
}

然后你可以在你的TeacherStudent中实现这个接口。

public class Student : SchoolEntity { }
public class Teacher : SchoolEntity { }

最后,可以使用枚举使形参更清晰一些。它们在读取时会更清晰,而不是具有相同的参数类型。注意函数重载不考虑返回类型作为签名差异

enum Entity { Teacher, Student }

然后您可以检查返回哪些数据。

public SchoolEntity dbSelect(Entity type)
{
    switch(type) {
         case Teacher:
             var query = "SELECT * FROM Teacher";
             return dbConnect(query, true);
         // Rest of the cases.
    }
}

请注意,您的SQL语句对SQL注入是开放的,任何人都可以删除表,或者执行可以传递给引擎的操作。

在列表中工作

使用列表不是一个好主意。毕竟,你会返回什么列表?是public List<Teacher> dbSelect还是public List<Student> dbSelect ?这个问题的答案和解决方法是用一个相同的类型来备份这两种类型。

dbSelect函数

请注意,您仍然只返回Teacher类型,那么为什么您有一个学生呢?你一定要把它扔回去。事实上,如果我要开发这个。我必须使用dbSelect函数将Entity作为参数,以便将所有数据库请求和处理保存在单个函数中。

public List<Teacher> dbConnect(Entity type)
{
    SQLiteConnection conn = null;
    SQLiteCommand command = null;
    SQLiteDataReader reader = null;
    Teacher result = null; // Can be set to null.
        //    try
        {
            conn = new SQLiteConnection(db.db);
            conn.Open();
            string query;
            // This way, leave the function to build the query.
            if(type == Entity.Teacher) {
                query = "SELECT * FROM Teacher";
            } else {
                query = "SELECT * FROM Student";
            }
            command = new SQLiteCommand(query, conn);
            reader = command.ExecuteReader();
        }
        //   catch (Exception ex) { }
        while (reader.Read())
        {
            if(type == Entity.Teacher) {
                Teacher temp = new Teacher(
                    reader[0].ToString(),    
                    reader[1].ToString(),                              
                    reader[2].ToString(),                              
                    reader[3].ToString(),                              
                    reader[4].ToString(), 
                    reader[5].ToString(),                              
                    reader[6].ToString(),                              
                    reader[7].ToString()                               
                );
                result.Items.Add(temp);
            } else {
                // Add the student.
            }
        }
    conn.Close();
    return result;
}

现在在这段代码中,您知道result的类型是Teacher。那里没有列表,这使得你的代码有点混乱。听我的建议:重写代码。

请浏览以下有用的连结:

显式接口实现
https://en.wikipedia.org/wiki/SQL_injection
签名和重载