C# 在C中创建一个可以处理多个返回类型的函数#
我对C#比较陌生,以前大部分编程都是用VB6完成的。我知道C#的类型比VB明确得多,但我希望我的问题有一个解决方案 我正在从事一个项目,该项目旨在打开、解析、验证并最终编辑5个不同的CSV文件,这些文件用作我们使用的应用程序的输入。手动操作CSV文件是现在要做的事情,但由于缺乏原始开发人员的文档和支持,对大多数用户来说很困难。我的目标是构建一个GUI,允许用户直接编辑字段并创建一个新的CSV文件以用作导入。以下是现在的基本结构:C# 在C中创建一个可以处理多个返回类型的函数#,c#,c#-3.0,C#,C# 3.0,我对C#比较陌生,以前大部分编程都是用VB6完成的。我知道C#的类型比VB明确得多,但我希望我的问题有一个解决方案 我正在从事一个项目,该项目旨在打开、解析、验证并最终编辑5个不同的CSV文件,这些文件用作我们使用的应用程序的输入。手动操作CSV文件是现在要做的事情,但由于缺乏原始开发人员的文档和支持,对大多数用户来说很困难。我的目标是构建一个GUI,允许用户直接编辑字段并创建一个新的CSV文件以用作导入。以下是现在的基本结构: public class Dataset { public
public class Dataset
{
public Dictionary<string,File1> file1 = new Dictionary<string,File1>();
public Dictionary<string,File2> file2 = new Dictionary<string,File2>();
public Dictionary<string,File3> file3 = new Dictionary<string,File3>();
public Dictionary<string,File4> file4 = new Dictionary<string,File4>();
public Dictionary<string,File5> file5 = new Dictionary<string,File5>();
public void SelectFiles()
{
//User specifies which file(s) are to be opened (default is all 5 files)
}
public class File1
{
public string Field_1 {get ; set}
public string Field_2 {get ; set}
.
.
.
public string Field_10 {get ; set}
}
public class File2
{
public string Field_1 {get ; set}
public string Field_2 {get ; set}
.
.
.
public string Field_31 {get ; set}
}
public class File3
{
public string Field_1 {get ; set}
public string Field_2 {get ; set}
.
.
.
public string Field_57 {get ; set}
}
public class File4
{
public string Field_1 {get ; set}
public string Field_2 {get ; set}
.
.
.
public string Field_68 {get ; set}
}
public class File5
{
public string Field_1 {get ; set}
public string Field_2 {get ; set}
.
.
.
public string Field_161 {get ; set}
}
}
公共类数据集
{
公共字典文件1=新字典();
公共字典文件2=新字典();
公共字典文件3=新字典();
公共字典文件4=新字典();
公共字典文件5=新字典();
public void SelectFiles()
{
//用户指定要打开的文件(默认为所有5个文件)
}
公共类文件1
{
公共字符串字段_1{get;set}
公共字符串字段_2{get;set}
.
.
.
公共字符串字段_10{get;set}
}
公共类文件2
{
公共字符串字段_1{get;set}
公共字符串字段_2{get;set}
.
.
.
公共字符串字段_31{get;set}
}
公共类文件3
{
公共字符串字段_1{get;set}
公共字符串字段_2{get;set}
.
.
.
公共字符串字段_57{get;set}
}
公共类文件4
{
公共字符串字段_1{get;set}
公共字符串字段_2{get;set}
.
.
.
公共字符串字段_68{get;set}
}
公共类文件5
{
公共字符串字段_1{get;set}
公共字符串字段_2{get;set}
.
.
.
公共字符串字段_161{get;set}
}
}
挑战在于将CSV中的数据读入每个词典。现在这是用5个不同的函数完成的(实际上一个函数重载了5次)
公共字典readfile(字符串文件)
{
//打开并解析文件#1,并存储在File1类中,由File1字典访问
}
公共字典ReadFile(字符串文件)
{
//打开并解析文件#2,并存储在File2类中,由File2字典访问
}
公共字典ReadFile(字符串文件)
{
//打开并解析文件#3,并存储在File3类中,由File3字典访问
}
公共字典ReadFile(字符串文件)
{
//打开并解析文件#4,并存储在File4类中,由File4字典访问
}
公共字典ReadFile(字符串文件)
{
//打开并解析文件#5,并存储在File5类中,由File5字典访问
}
打开和解析CSV文件的代码实际上完全相同,只是字典的类型不同。因此,当我对这个函数进行更改时,我必须确保对其他4个函数进行了相同的更改,我担心这会使将来维护代码变得更加困难。是否有任何可能的方法可以创建一个没有重载的函数,在这里我可以将类型作为参数传递给函数
public Dictionary<string,[UnknownType]>ReadFile(string file, [UnknownType] typ)
{
//Open and Parse File and read into class specified by typ
}
publicDictionaryReadFile(字符串文件,[UnknownType]类型)
{
//打开并解析文件并读入由typ指定的类
}
必须使文件
类继承基类并返回它:
public abstract classFileBase
{
// include common features here
}
public class File1 : FileBase
{
public string Field_1 {get ; set}
public string Field_2 {get ; set}
.
.
.
public string Field_10 {get ; set}
}
public Dictionary<string, FileBase>ReadFile(string file)
{
//Open and Parse File and read into class specified by typ
}
公共抽象类文件库
{
//在此处包括常见功能
}
公共类File1:FileBase
{
公共字符串字段_1{get;set}
公共字符串字段_2{get;set}
.
.
.
公共字符串字段_10{get;set}
}
公共字典ReadFile(字符串文件)
{
//打开并解析文件并读入由typ指定的类
}
为什么不为“未知”类型使用object(所有.NET类型的基础)?然后,您可以根据需要对其进行测试/强制转换
但是,函数重载有什么问题吗?似乎非常适合这种情况。不要忘记,您可以有5个公共重载函数,然后这些函数可以委托给私有函数,以任何方式实现您的目标。面向对象,我的朋友。从VB6的角度来看,这可能不是您所习惯的。但是,与其使用File1->File5,不如使用一个“CVSFile”--对象,如果您确实需要的话,可以从中派生出来。这会在很多方面帮助你 多态性 查看MSDN,了解如何使用 MSDN中的代码片段:
public class BaseClass
{
public void DoWork() { }
public int WorkField;
public int WorkProperty
{
get { return 0; }
}
}
public class DerivedClass : BaseClass
{
public new void DoWork() { }
public new int WorkField;
public new int WorkProperty
{
get { return 0; }
}
}
DerivedClass B = new DerivedClass();
B.DoWork(); // Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork(); // Calls the old method.
编辑
只是想澄清一下
当使用new关键字时,new
调用类成员而不是
已删除的基类成员
替换。那些基类成员是
称为隐藏成员。隐藏类
如果出现以下情况,仍然可以调用成员:
派生类的实例被强制转换
到基类的实例
如果您想改用虚拟方法:
为了获得一个派生的
类完全接管一个类
来自基类的成员,基类
类必须将该成员声明为
事实上的这是通过
将virtual关键字添加到
成员的返回类型。派生的
类则可以选择使用
覆盖关键字,而不是新关键字,以
替换基类实现
用它自己的
在这种情况下,结果将是这样
DerivedClass B = new DerivedClass();
B.DoWork(); // Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork(); // Also calls the new method.
所有示例均取自MSDN
如何将此应用于您的示例
假设您有一个LoadCSV方法,而不是有5个不同的方法返回每个对象,您可以很容易地说“嘿,我将返回一个CVSFile,您不关心其他任何事情!”
那里有很多不错的电视剧,还有“儿童节目”
public class BaseClass
{
public virtual void DoWork() { }
public virtual int WorkProperty
{
get { return 0; }
}
}
public class DerivedClass : BaseClass
{
public override void DoWork() { }
public override int WorkProperty
{
get { return 0; }
}
}
DerivedClass B = new DerivedClass();
B.DoWork(); // Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork(); // Also calls the new method.
public abstract class FileBase
{
public virtual void DoSomeParsing()
{
}
}
public class File1 : FileBase
{
}
public class Test
{
public Dictionary<string, T> ReadFile<T>(string file) where T : FileBase, new()
{
Dictionary<string, T> myDictionary = new Dictionary<string, T>();
myDictionary.Add(file, new T());
myDictionary[file].DoSomeParsing();
return myDictionary;
}
public object Testit()
{
Test test = new Test();
return test.ReadFile<File1>("C:\file.txt");
}
}
Dictionary<string, T> ReadFile<T>(string f) {...}
...
Dictionary<string, File1> d = ReadFile<File1>(filename);
class Base {
virtual ReadFile();
}
class File1: Base {
override ReadFile(); //Reads File1
}
class File2: Base {
override ReadFile(); //Reads File2
}
List<Base> baseList
if(I need to read file File1)
baseList.Add(new File1());
public interface IParser
{
object Parse(string input);
}
public interface IParser<T> : IParser
{
new T Parse(string input);
}
public class MyParser : IParser<MyObject>
{
#region IParser<MyObject> Members
public MyObject Parse(string input)
{
if (string.IsNullOrEmpty(input))
throw new ArgumentNullException("input");
if (input.Length < 3)
throw new ArgumentOutOfRangeException("input too short");
return new MyObject()
{
Field1 = input.Substring(0, 1),
Field2 = input.Substring(1, 1),
Field3 = input.Substring(2, 1)
};
}
object IParser.Parse(string input)
{
return this.Parse(input);
}
#endregion
}
public class MyObject
{
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
}
public static class ToolKit
{
public static Dictionary<string, TResult> ReadFile<TParser, TResult>(
this string fileName)
where TParser : IParser<TResult>, new()
where TResult : class
{
return fileName.AsLines()
.ReadFile<TParser, TResult>();
}
public static Dictionary<string, TResult> ReadFile<TParser, TResult>(
this IEnumerable<string> input)
where TParser : IParser<TResult>, new()
where TResult : class
{
var parser = new TParser();
var ret = input.ToDictionary(
line => line, //key
line => parser.Parse(line)); //value
return ret;
}
public static IEnumerable<string> AsLines(this string fileName)
{
using (var reader = new StreamReader(fileName))
while (!reader.EndOfStream)
yield return reader.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
var result = new[] { "123", "456", "789" }
.ReadFile<MyParser, MyObject>();
var otherResult = "filename.txt".ReadFile<MyParser, MyObject>();
}
}
List<List<string>> Parse(string file)
{
List<List<string>> result = new List<List<string>>();
using (TextReader reader = File.OpenText(file))
{
string line = reader.ReadLine();
while (line != null)
{
result.Add(new List<string>(line.Split(',')));
line = reader.ReadLine();
}
}
return result;
}
Dictionary<int, File1> file1 = Parse("file1.csv");
Console.Write(file1[0].Field_5);
List<List<string>> file1 = Parse("file1.csv");
Console.Write(file1[0][5]);
List<List<string>> file1 = Parse("file1.csv");
Console.Write(file1[0]["SomeFieldName"]);