C# 如何确定属性/字段是否为引用类型(使用反射)

C# 如何确定属性/字段是否为引用类型(使用反射),c#,reflection,C#,Reflection,我已经签出了链接。有一个问题是,通常有一个不确切的术语“参考”。所以首先我想澄清一下,在我看来,什么时候类型是引用类型 string bla = "abc"; string blob = bla; bla = "cde"; // bla = "cde" and blob = "abc" 这是非引用类型的行为 string bla = &

我已经签出了链接。有一个问题是,通常有一个不确切的术语“参考”。所以首先我想澄清一下,在我看来,什么时候类型是引用类型

        string bla = "abc";
        string blob = bla;
        bla = "cde";
        // bla = "cde" and blob = "abc"
这是非引用类型的行为

        string bla = "abc";
        string blob = bla;
        bla = "cde";
        // bla = "cde" and blob = "abc"
这是引用类型的行为

        Person jens = new Person("Jens");
        Person frank = jens; // doesn't make any sense i know
        frank.Name = "Frank";
        //jens.Name = "Frank" and frank.Name = "Frank"
正如您所看到的,一旦引用,只有类型传递引用(如c中的指针)。您还可以通过使用ref关键字来实现非引用类型的行为

我搜索的是Type类的一个属性,它指示该类型是否为引用类型

它也应该适用于结构,只适用于任何可以“存储”某些内容的东西

根据我在上面提供的链接,有多个属性,都略有不同

  • 一类
  • 基本的
  • IsValueType
我需要用哪一个? 他们似乎都不符合我的条件


对不起,我的英语不好:)

IsValueType
是您要找的


请注意:
string
实际上是一种引用类型。

string
是一种特殊的内置类型,如
Int32
Double
,它具有特殊的属性,可以用C#将其表示为文字值。两者都是,我想这可能与你正在努力解决的问题有关

我的猜测是,你对C#中引用的含义做出了一些错误的假设。两种语言中都使用了
reference
struct
这两个词,但它们各自的含义非常不同

在第二个示例中,
frank
jens
都是对同一实际对象的引用。可以将它们看作是指向内存中相同地址的指针,因为它们在内存中的某个地方

看起来您认为当您将
jens
分配给
frank
时,您正在调用一个复制构造函数。如果<代码> JNEs/COD>和 Frank 是C++中的堆栈变量,那就是会发生的。但是C++不是C++。C#引用是可重新绑定的。就赋值而言,它就像C++中的指针,而不是C++引用。但是与C++指针不同,你不能用它来做指针运算,你不需要去引用它。p> 在C#中,当您想要复制引用类型的实例,例如
String
或(显然)
Person
,您需要明确地执行此操作

//  Assume Person has a Person(String name) constructor
Person bob = new Person("Bob");

//  This assigns a **reference to bob** to a new reference variable.
//  steve and bob are now referencing the same object. Not what you want.
Person steve = bob;

//  Person should have a copy constructor. If that's done correctly, 
//  this will create a COPY of the object that both steve and bob
//  refer to. 
Person bob2 = new Person(steve);

//  Because we explicitly created a new instance for bob2, this won't
//  affect the other "Bob" instance that bob and steve still refer to.
bob2.Name = "Bob Junior";
C#中的“非引用”类型称为
struct
<代码>日期时间就是一个例子。复制时,C<代码>结构> /COD>就像堆栈上的C++类实例:有一个隐式拷贝。
//  DateTime is a struct. It's IsValueType, NOT IsClass. 
//  Different behavior. 
DateTime today = DateTime.Now.Date;

//  This creates a copy, because DateTime is a struct not a class.
DateTime alsoToday = today;

这仅仅是(值得称赞的)对语言的普遍好奇,还是你正在试图解决一个特定的问题?我经常发现,当有人问“你为什么真的要这么做?”时,答案会让我们比专注于你试图用来解决问题的特定技术时更有帮助。像这样的问题通常是暗示OP从错误的解决方案开始

你的两种方法做了两件不同的事情。在第一个示例中,您为
X
赋值,在第二个示例中,您为
X.a
赋值,然后询问“为什么
X
的值没有改变。@ScottChamberlain我先对X=y进行赋值,然后再对y.A进行赋值,只是为了表明X.A已经变为yes,但对于字符串版本,您不会执行
y.A
。如果类
String
具有公共setter的属性,则可以对其执行相同的操作。要使示例等效,请替换
frank.Name=“frank”
jens=新人(“弗兰克”)并查看frank和jens的价值。在处理字符串时,假设只键入
“stuff”
实际上是在做
新字符串(新字符[]{'s','t','u','f','f'})
,您看到的行为更有意义。@ScottChamberlain您是对的,但是在上面的示例中,如果使用'int'而不是'String'?事实上,我只是想展示我的行为举止。我是一个没有经验的程序员,所以如果我写的问题不总是100%准确的话,请原谅我。字符串的赋值运算符不显示值语义。所有字符串都是,是一个没有公共setter的类。它是一个不可变的对象。“假装是值类型”一点也不奇怪只要你使用返回字符串的方法(包括
操作符+
),只读对象就会创建新的只读对象这不仅是一个事实上错误的答案,它也没有解决OP困惑的明显根源。我曾经在德语背景下学习c语言编程,所以我一直在为这些名字而挣扎。不变性这个词对我来说是新的。所以非常感谢你的帮助。@LuckyLike有一件事我忘了提:你在这里想要实现的实际目标是什么?