我来自JavaScript并试图更好地理解在C#中使用对象。我有一些简单的代码:
class Program
{
static void Main(string[] args)
{
MyClass firstObj = new MyClass();
firstObj.Number = 6;
Console.WriteLine(firstObj.Number);
object secondObj = doResults();
string getString = secondObj.GetType().GetProperty("resultsString").GetValue(secondObj).ToString();
Console.WriteLine(getString);
Console.ReadLine();
}
public static object doResults()
{
ResultsObj newResults = new ResultsObj();
newResults.resultsString = "Here is my string";
return newResults;
}
}
public class MyClass
{
public int Number { get; set; }
}
public class ResultsObj
{
public string resultsString { get; set; }
}
在Main()的第一部分中,我创建了一个对象,添加了一个属性,设置了一个值,然后访问并显示了该值。它非常直接。
在Main()的第二部分中,我调用doResults()方法,该方法创建一个字符串属性对象。
我的问题是这一行:
string getString = secondObj.GetType().GetProperty("resultsString").GetValue(secondObj).ToString();
对我来说似乎很牵扯。这真的是访问返回对象属性的正确/最有效的方法吗?
答案 0 :(得分:9)
C#和JavaScript之间的根本区别在于C#是一种强类型语言。在main
方法中,您没有“添加属性”,您可以设置现有属性的值。您遇到这么多麻烦的原因是您的参考变量不是正确的类型。
类型是对象实例的属性和方法(蓝图)的集合。这类似于JavaScript,除了在JavaScript中您可以在运行时添加属性和方法,在C#中您不能,您只能在编写代码时可用的内容(ExpandoObject除外,这是一个更高级的概念)。编译器只允许您访问由用于进行该引用的变量的类型定义的属性和方法。当您从方法返回object
时,您会说“此方法的调用方只能访问object
的属性和方法”。
所以基本上你需要决定你希望消费者能够访问哪些属性和方法(即 type )。在这种情况下,您的方法创建ResultsObj
的实例并返回它,因此返回类型应定义为ResultsObj
。
public static ResultsObj doResults()
{
ResultsObj newResults = new ResultsObj();
newResults.resultsString = "Here is my string";
return newResults;
}
现在,您的调用代码知道它返回的是ResultsObj
可以访问该类型的属性和方法。
ResultsObj secondObj = doResults();
Console.WriteLine(secondObj.resultsString);
这一切都归结为类型。重申一下,编译器只允许您访问由引用变量定义的 type 的属性和方法。
顺便说一句,你也可以把第二段代码写成:var secondObj = doResults();
Console.WriteLine(secondObj.resultsString);
这可能看起来令人困惑,尤其是来自JavaScript背景,其中var
意味着不同的东西。在这种情况下,C#正在进行隐式输入。由于方法doResults()
被定义为返回ResultsObj
,因此隐式输入变量secondObj
。如果您尝试编写以下代码,则无法编译,因为隐式输入已经确定secondObj
是ResultObj
,并且您无法为ResultsObj
类型的变量分配数字。
var secondObj = doResults();
secondObj = 1; // This would cause a compiler error
答案 1 :(得分:5)
不,使用反射肯定不是最有效的方法。但更重要的是,它也不是最易读的方式。编写编译时类型安全的代码。
您应该返回正确的Object
:
ResultsObj
public static ResultsObj doResults()
{
ResultsObj newResults = new ResultsObj();
newResults.resultsString = "Here is my string";
return newResults;
}
然后它简单易读,安全有效:
ResultsObj secondObj = doResults();
string getString = secondObj.resultsString;
如果您无法更改类型,并且必须使用Object
,则可以cast将其输入正确的类型:
object secondObj = doResults();
ResultsObj resultObj = (ResultsObj) secondObj;
string getString = resultObj.resultsString;
答案 2 :(得分:3)
在C#中我们有类型安全,所以尽可能使用它。因此,不是返回object
,而是返回您正在使用的类型,例如:
public static ResultsObj doResults()
{
ResultsObj newResults = new ResultsObj();
newResults.resultsString = "Here is my string";
return newResults;
}
然后你就这样使用它:
ResultsObj secondObj = doResults();
secondObj.resultsString = "blah";
另一个替代方案(我在这里只提到它因为它在某些情况中很有用,所以默认情况下不要这样编码)是使用类型dynamic
。这将删除所有类型检查,但意味着您需要注意代码:
dynamic secondObj = doResults();
secondObj.resultsString = "blah"; //this will work
secondObj.NonExistantProperty = "blah"; //this will compile but fail at runtime
答案 3 :(得分:3)
1.返回ResultsObj
而不只是object
:
public static ResultsObj doResults()
{
ResultsObj newResults = new ResultsObj();
newResults.resultsString = "Here is my string";
return newResults;
}
2.用正确的左手方法调用方法:
ResultsObj res = doResults();
Console.Write(res.resultsString);
P.S。:左侧可以是var(编译器功能),如js:
var res = doResults();
Console.Write(res.resultsString);
答案 4 :(得分:2)
变化:
public static object doResults()
为:
public static ResultsObj doResults()
然后:
string getString = secondObj.resultsString;