C#不通过返回类型推断重载方法

时间:2014-06-23 18:44:16

标签: c# overloading

我正在编写一个C#程序集来抓取目录,并给我一个文件列表,其中最后一行CSV行中的日期小于当前日期。由于这是一个程序员,我实际上并没有花太多时间使代码非常干净或任何东西 - 但我认为这完全是一个意见问题。

奇怪的是以下一组代码片段。三个静态方法都在同一个类中。

   public static DateTime dateStringConverter(string mmddyyyy, char delim='/')
    {
            string[] date = mmddyyyy.Split(delim);
            DateTime fileTime = new DateTime(Convert.ToInt32(date[2]), Convert.ToInt32(date[0]), Convert.ToInt32(date[1]));
            return fileTime;
    }

        public static string dateStringGetter()
        {
            string sYear = DateTime.Now.Year.ToString();
            string sMonth = DateTime.Now.Month.ToString().PadLeft(2, '0');
            string sDay = DateTime.Now.Day.ToString().PadLeft(2, '0');
            return sMonth + '/' + sDay + '/' + sYear;
        }

        public static DateTime dateStringGetter()
        {
            string datestring = dateStringGetter();
            return dateStringConverter(datestring);
        }

错误消息显示:

Error   1   Type 'Poller.Program' already defines a member called 
'dateStringGetter' with the same parameter types    

问题方法是dateStringGetter()的第二个重载副本,当然它与第二个版本(无)具有相同的参数类型,但有两个完全不同的返回类型。一个是DateTime,另一个是字符串。具有DateTime返回类型的版本(在编码错误的字符串中)使用字符串类型调用dateStringGetter()的版本。

这不是很好奇吗?那个C#不会单独根据返回类型重载方法吗?我想我已经完成了库的重载,它会根据调用自动检测我想要的返回类型 - 但我不确定。对此我感觉不对劲。

所以我认为C#不会超载返回类型?

6 个答案:

答案 0 :(得分:9)

  

所以我认为C#不会超载返回类型?

不,确实没有。返回类型不是签名的一部分。

从C#5规范的第3.6节(强调我的):

  

方法的签名包括方法的名称,类型参数的数量以及每个形式参数的类型和种类(值,参考或输出),按从左到右的顺序考虑。出于这些目的,在形式参数类型中出现的方法的任何类型参数不是通过其名称来标识,而是通过其在方法的类型参数列表中的序号位置来标识。 方法的签名特别不包括返回类型,可能为最右侧参数指定的params修饰符,也不包括可选的类型参数约束。

  

重载方法允许类,结构或接口声明具有相同名称的多个方法,前提是它们的签名在该类,结构或接口中是唯一的。

另外(为了完整性):

  

虽然outref参数修饰符被视为签名的一部分,但在单一类型中声明的成员只能通过refout在签名方面有所不同。

除了其他任何东西之外,这种限制有助于提高可读性 - 即使它们因参数而异,也很难分辨出哪些重载被调用 - 如果方法可能被返回类型重载,那就更糟了。在这种情况下,对于重载方法甚至没有意义,因为它们相反的事物。如果所有重载执行相同的基本任务,则只应重载方法。

作为旁注,您的方法目前不遵循.NET命名约定 - 您应该使用标准格式化/解析方法而不是自己编辑。

答案 1 :(得分:2)

不,C#(就像之前的C ++一样)不允许重载,其中唯一的区别在于返回类型

这里的一个大问题是,如果你没有分配返回值,你会打电话给哪一个?如果两种类型都可以转换为返回值赋值,那么您可以调用哪一个?它非常模糊,所以不允许。

答案 2 :(得分:1)

基于"编程程序来抓取目录并给我一个文件列表,其中最后一行CSV行中的日期小于当前日期。由于这是一个程序,我并没有真正花太多时间使代码非常干净或任何东西"我提出了类似于我过去使用的以下内容。拿走或离开它。

它的作用:指定一个根目录,函数获取给定类型的目录中的所有文件(根据您的时间要求,修改files.add(...)以符合您的标准)

因为你说你不想花太多时间在这上面,所以只留下这个作为你工作的替代品。

    var data = GetAllFilesOfType('c:\rootpath', 'csv')
/// <summary>
    /// Gets files of specified type and appends them to the file list.
    /// </summary>
    /// <param name="basepath">Starting file path</param>
    /// <param name="type">File type - Do not include prefix ('txt' instead of '*.txt</param>
    /// <returns>Returns results of WalkDirectoryTree</returns>
    public static IEnumerable<FileInfo[]> GetAllFilesOfType(string basepath, string type)
    {
        var root = new DirectoryInfo(basepath);
        return WalkDirectoryTree(root, type);
    }


/// <summary>
    /// Recursively gets all files from a specified basepath (provided by GetAllFilesOfType)
    /// and appends them to a file list. This method reports all errors, and will break on
    /// things like security errors, non existant items, etc.
    /// </summary>
    /// <param name="root">Initially specified by calling function, set by recursive walk</param>
    /// <param name="type">File type that is desired. Do not include prefix ('txt' instead of '*.txt')</param>
    /// <returns></returns>
    private static List<FileInfo[]> WalkDirectoryTree(DirectoryInfo root, string type)
    {
        var files = new List<FileInfo[]>();

        //Traverse entire directory tree recursively - Will break on exception
        var subDirs = root.GetDirectories();
        foreach (var data in subDirs.Select(dirInfo => WalkDirectoryTree(dirInfo, type)).Where(data => data.Count > 0))
        {
            files.AddRange(data);
        }
        //If any file is found, add it to the file list
        if (root.GetFiles(string.Format("*.{0}", type)).Length > 0)
        {
            files.Add(root.GetFiles(string.Format("*.{0}", type)));
        }
        //Kicks the file list up a level until it reaches root, then returns to calling function
        return files;
    }

答案 3 :(得分:1)

不幸的是,始终有办法将其锤击到位:

class Program
{
    static void Main(string[] args)
    {
        object stringDate = "";
        object dateTime = new DateTime();
        DateUtils.DateStringGetter(ref stringDate);
        DateUtils.DateStringGetter(ref dateTime);
    }
}

public static class DateUtils
{
    private static DateTime DateStringConverter(string mmddyyyy, char delim = '/')
    {
        string[] date = mmddyyyy.Split(delim);
        DateTime fileTime = new DateTime(Convert.ToInt32(date[2]), Convert.ToInt32(date[0]),
            Convert.ToInt32(date[1]));
        return fileTime;
    }

    public static void DateStringGetter(ref object date)
    {
        string sYear = DateTime.Now.Year.ToString();
        string sMonth = DateTime.Now.Month.ToString().PadLeft(2, '0');
        string sDay = DateTime.Now.Day.ToString().PadLeft(2, '0');

        if (date is String)
        {
            date = sMonth + '/' + sDay + '/' + sYear;
        }

        if (date is DateTime)
        {
            date = DateStringConverter(sMonth + '/' + sDay + '/' + sYear);
        }

    }
}

答案 4 :(得分:0)

您不能只为返回类型提供两种不同的方法,因为代码无法推断哪些方法应该是返回类型。

答案 5 :(得分:0)

正确,C#不允许您仅对返回类型重载方法。

如果我只是在没有返回值的情况下调用dateStringGetter(),请考虑会发生什么。

我打过哪种方法?