在C#中,我们在类型字符串上有这个非静态方法:
"abc".ToUpper()
但是对于char,我们需要使用静态方法:
char.ToUpper('a')
在向初学者介绍c#时,他们总是希望能够编写以下内容:
'a'.ToUpper()
有没有人有这样设计的见解?
我唯一能想到的就是性能,但我也期望为类型字符串提供一个静态的ToUpper()。
答案 0 :(得分:1)
区别在于string
是reference type,而char
是代表.Net Framework Char Structure的关键字。当你调用Char.ToUpper('a')
时,你实际上是在C#中使用字符串结构。结构是Value Types。值类型是不可变的。
由于结构是不可变的,因此对结构本身起作用的方法不能按预期工作(see Why are Mutable Structs Evil)。因此需要静态方法。调用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'
char有其他允许你执行'a'.Equals('a');
之类的方法的原因是因为值类型和引用类型都继承自Object,它定义了那些方法(从技术上讲,值类型的类型为{ {1}},继承自System.ValueType
)。这些方法不会对对象本身进行任何更改。
我非常好奇,看看是否有“为什么System.Object
没有char
方法”的实际答案,我决定查看CSharp 5 Language Specification Document,我找到了以下内容:
.ToUpper()
是一个积分类型(第80页),它是简单类型的子集。简单类型本身只是预定义的结构类型。结构类型是“可以声明常量,字段,方法,属性,索引器,运算符,实例构造函数,静态构造函数和嵌套类型”的值类型“(第79页)。
char
是一种类型,它是一种参考类型(第85页)。类类型定义“包含数据成员(常量和字段)的数据结构,函数成员(方法,属性,事件,索引器,运算符,实例构造函数,析构函数和静态构造函数)和嵌套类型” (第84页)。
此时,string
s显然可以支持char
方法(这就是扩展方法有效的原因)。但是,正如问题所述,他们不支持。 在这一点上,我确信任何关于为什么这是真的的推理都是纯粹的推测(当然,除非你是C#团队的成员)。
答案 1 :(得分:0)
Hans Passant提到可以通过扩展方法轻松实现此语法。我会在这里提供代码,以防任何人对使用该语法深感依恋。
public static class MyExtensionMethods
{
public static char ToUpper( this char c )
{
return char.ToUpper( c );
}
}
然后你可以这样做:
'a'.ToUpper()
答案 2 :(得分:0)
(抱歉,评论中没有足够的空间 - 我知道这不是一个完整的答案。)
这似乎是所有原始类型的模式;例如,int
,double
和bool
也没有方法(ToString()
个变种除外)。所以它不仅仅是char
- 它是c#定义的所有原始类型的属性。
我猜(并且这是猜测),无论何时访问数据,您都要直接访问RAM的位 - 原始值如int
和char
以及{{1 - 或者您正在访问像对象或结构一样的.NET构造。 char在特定内存地址处始终为2个字节。因此框架可以将其视为原始内存位置。
如果我们尝试将原始RAM视为对象,您将要么必须“装箱”所有工作,或者只是不可能。我的猜测是你不能在基元上做一些像virtual method dispatch这样的核心功能,并且对象的世界和基元的世界必须分开。
无论如何,希望在某种程度上促进谈话......