【问题标题】:c# What's the difference between a generic method and a method that takes in objects as parameters? [duplicate]c#泛型方法和将对象作为参数的方法有什么区别? [复制]
【发布时间】:2018-11-26 20:43:03
【问题描述】:
static void Swap<T>(ref T var1, ref T var2)
{
    T temp = var1;
    var1 = var2;
    var2 = temp;
}

static void Swap2(ref object var1, ref object var2)
{
    object temp = var1;
    var1 = var2;
    var2 = temp;
}

我认为 Swap 在某些方面比 Swap2 更可取?

【问题讨论】:

  • Swap 将确保两个参数具有相同的类型(或基本类型)。
  • 那么Swap2其实更灵活?
  • 好吧,如果您不重视类型安全或性能 - 当然,它更灵活。
  • 要了解区别,请为这两种方法(调用者)编写一些代码,尝试交换两个字符串的值,然后是两个整数。您会注意到调用Swap 的代码编写起来相当简单。
  • 对于值类型,例如int,在调用object 版本的方法时,值必须先装箱然后再拆箱,但在调用通用版本时则不需要。对于引用类型,在调用object 版本时,此代码中没有任何内容可以确保两个对象是相同甚至兼容的类型。

标签: c#


【解决方案1】:

这个问题已经回答了很多次,所以如果这个问题被投票结束,请不要感到惊讶。

在您的示例中,由于方法是无效的,并且它们只是相互引用,因此没有区别。然而;如果添加了where T : {the base type to filter against},则可以使用Swap&lt;T&gt; 过滤基本类型

出于各种原因,泛型通常比使用对象更好,但第一可能应该是装箱/拆箱。 (这在您的示例中没有发生。)

当您使用object 时,您必须将其转换为预期使用它的类型。这会导致大量开销和潜在错误。当您使用泛型时,您有编译时类型,因此您可以在编译之前或编译期间捕获许多异常,您可以使用更强大的类型,最重要的是您不应该处理任何装箱/拆箱(这会降低性能)。

要考虑的另一件事是,当您在示例中使用Swap&lt;T&gt; 时,您会强制两者相同Type,因为T 不能同时是不同的类型。使用Swap2,您可以重新引用任意两个对象;但是,您将不得不手动将这些类型转换为对象,并且它们无法恢复到原始类型,因为除非两者一开始就属于同一类型。

记住ref 参数不会从多态中受益。 T 参数是通用的,但由于我们只有一个 T,所以类型总是相同的。

using System;

namespace Question_Answer_Console_App
{
    class Program
    {

        static void Main(string[] args)
        {
            var text = "Hey There";
            var employer1 = new Employer() { Name = "Microsoft" };
            var employer2 = new Employer() { Name = "EA Games" };

            //Generic Swap
            SwapGeneric(ref employer1, ref employer2);
            //Swap(ref text, ref employee2); //<- compiler error. Cannot be inferred by the usage.

            Console.WriteLine("Types of the same swapped");
            Console.WriteLine(employer1.Name);
            Console.WriteLine(employer2.Name);
            Console.WriteLine();
            //object Swap
            //SwapObject(ref employee1, ref employee2); //- compiler error.  Cannot convert to ref object.

            //Reference string and employer as object.
            var textObject = text as object;
            var employerObject = employer1 as object;

            SwapObject(ref textObject, ref employerObject);

            //Existing types cannot be re-referenced.
            //text = (Employer)textObject; //<-compiler error.  Cannot implicitly convert...
            //employer1 = (string)employerObject; //<-compiler error. Cannot implicitly convert....

            //We can cast objects to swapped types succesfully but see how easily this can cause error and confusion.
            Console.WriteLine("Objects of different types swapped");
            Console.WriteLine(((Employer)textObject).Name);
            Console.WriteLine((string)employerObject);

            Console.ReadKey();
        }

        static void SwapGeneric<T>(ref T var1, ref T var2)
        {
            T temp = var1;
            var1 = var2;
            var2 = temp;
        }

        static void SwapObject(ref object var1, ref object var2)
        {
            object temp = var1;
            var1 = var2;
            var2 = temp;
        }
    }

    public class Employer
    {
        public object Name { get; set; }
    }
}
//OUTPUT
//Types Swapped
//EA Games
//Microsoft

//Objects Swapped
//EA Games
//Hey There

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    • 2013-09-20
    • 2011-11-15
    • 2021-02-08
    相关资源
    最近更新 更多