C# 使ToUpper成为Char上的静态方法背后的设计原因

C# 使ToUpper成为Char上的静态方法背后的设计原因,c#,C#,在C#中,我们在类型字符串上有一个非静态方法: "abc".ToUpper() 但是对于char,我们需要使用静态方法: char.ToUpper('a') 向初学者介绍c#时,他们总是希望能够编写以下内容: 'a'.ToUpper() 有人知道为什么它会这样设计吗 我唯一能想到的是性能,但我也希望类型字符串也有一个静态ToUpper()。Hans Passant提到,可以通过扩展方法轻松实现这种语法。我将在这里提供代码,以防有人对使用该语法有浓厚的兴趣 public static cla

在C#中,我们在类型字符串上有一个非静态方法:

"abc".ToUpper()
但是对于char,我们需要使用静态方法:

char.ToUpper('a')
向初学者介绍c#时,他们总是希望能够编写以下内容:

'a'.ToUpper()
有人知道为什么它会这样设计吗


我唯一能想到的是性能,但我也希望类型字符串也有一个静态ToUpper()。

Hans Passant提到,可以通过扩展方法轻松实现这种语法。我将在这里提供代码,以防有人对使用该语法有浓厚的兴趣

public static class MyExtensionMethods
{
    public static char ToUpper( this char c )
    {
        return char.ToUpper( c );
    }
}
然后你可以做:

'a'.ToUpper()
(抱歉,评论中没有足够的空间——我知道这不是一个完整的答案。)

这似乎是所有原始类型的一种模式<例如,code>int、
double
bool
也没有方法(除了
ToString()
变体)。因此,它不仅仅是char,它是c#定义的所有基本类型的属性

我猜(这是一个猜测),无论何时访问数据,您要么直接访问RAM的位,如
int
char
byte
,要么访问.NET结构,如对象或结构。一个字符在一个特定的内存地址上总是2个字节。因此,框架可以将其视为原始内存位置

如果我们试图将原始RAM视为对象,您要么必须“装箱”所有内容以执行任何工作,要么就是不可能。我的猜测是,你不能像在原语上那样做一些核心功能,而且对象的世界和原语的世界必须分开


无论如何,希望能在某种程度上推进对话…

区别在于
string
是一个,而
char
是一个表示.Net Framework的关键字。当您调用
Char.ToUpper('a')
时,实际上是在使用C#中的Char结构。结构是。值类型是不可变的

由于结构是不可变的,因此作用于结构本身的方法不能按预期工作()。因此,需要静态方法。调用
Char.ToUpper(aChar)
时,实际上并不是在更改aChar,而是在创建一个新的字符实例,该实例是作为参数传入的字符的大写表示形式,并返回它。下面的示例演示了这一点

Char aChar = 'a';
Char.ToUpper(aChar);
//aChar still equals 'a'

Char bChar = 'b';
bChar = Char.ToUpper(bChar);
//bChar now equals 'B'
reason char还有其他方法,允许您执行类似于
'a'.Equals('a')
是因为值类型和引用类型都继承自,后者定义了这些方法(从技术上讲,值类型是继承自
System.Object
的类型
System.ValueType
)。这些方法不会对对象本身进行任何更改

编辑-为什么这个问题实际上是猜测 由于我非常好奇地想知道“为什么
char
s没有
.ToUpper()
方法”是否有一个实际的答案,我决定查看,我发现了以下内容:

'a'.ToUpper()
char
是一个整数类型(第80页),它是简单类型的子集。简单类型本身只是预定义的结构类型。结构类型是“可以声明常量、字段、方法、属性、索引器、运算符、实例构造函数、静态构造函数和嵌套类型”的值类型(第79页)

string
是类类型,是引用类型(第85页)。类类型定义“包含数据成员(常量和字段)、函数成员(方法、属性、事件、索引器、运算符、实例构造函数、析构函数和静态构造函数)和嵌套类型的数据结构”(第84页)


此时,
char
s显然可以支持
.ToUpper()
方法(这就是扩展方法工作的原因)。然而,正如问题所述,他们不支持这一点在这一点上,我确信任何关于为什么这是真的的推理都是纯粹的推测(当然,除非你是C#团队的成员)。

我的怀疑是,仅仅是设计一个方法的人没有与创建另一个方法的人一起工作。@Khanh to:char是一个值类型,除非它是可空的,否则不能为空,这个问题与此无关。字符串可以为null,但是string.ToUpper()是一个实例方法,而null字符串上的ToUpper()会导致异常,因此…异议-推测调用:)Char是一个值类型,因此不可变,这样的方法无法工作。它可以写成返回大写字符的方法,如String.ToUpper()。但是你应该为.NET1.x中的拳击转换付费,这是当时没有考虑的最明显的原因。现在,您可以使用扩展方法轻松地添加它。这只是猜测,但我认为答案没有那么有趣:.Net 1.x主要基于Java,在Java中,原语不是对象,因此对于“char”值,您没有调用方法的选项,就像在“a”.toUpperCase()中一样,因此,在Java中,它们从一开始就为原语(Character.toUpperCase('a'))提供了一个静态方法样式,为String提供了一个成员方法,后者是一个对象(myStr.toUpperCase())。我的猜测是,C#只是遵循了同样的惯例。这并没有回答被问到的问题。这个问题想知道为什么不在这里是你如何做的,因为它也是不变的,所以我不知道为什么它在这里很重要。这绝不是期望“a”.ToUpper()改变值类型,只是返回大写值。@FrancoisBeaussier说得好。我最终研究了C#5的规范,这使我得出了与sara相同的结论(从您问题的评论部分)。请参阅我的编辑以了解更多解释。