简体   繁体   中英

More elegant or efficient way to access object properties?

I am coming from JavaScript and trying to better understand working with object in C#. I have some simple code:

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; }
}

In the first part of Main(), I create an object, add a property, set a value and then access and display that value. Its all pretty straight forward.

In the second part of Main(), I call the doResults() method, which creates an object a string property.

My questions is this line:

string getString = secondObj.GetType().GetProperty("resultsString").GetValue(secondObj).ToString();

It seems so involved to me. Is that really the proper/most efficient way to access the properties of the returned object?

The fundamental difference between C# and JavaScript is that C# is a strongly-typed language. In your main method you did not "add a property", you set the value of an existing property. The reason you're having so much trouble is that your reference variable is not of the correct type .

A type is a collection of properties and methods (a blueprint) for an object instance. This is similar to JavaScript except that in JavaScript you can add properties and methods at run-time and in C# you cannot, you are limited to what is available when the code is written (except for ExpandoObject which is a more advanced concept). The compiler will only let you access the properties and methods that are defined by the type of the variable being used to make that reference. When you return object from your method you are saying "the caller of this method can only access the properties and methods of an object ".

So basically you need to decide what properties and methods you want the consumer to be able to access (ie the type ). In this case your method creates an instance of ResultsObj and returns it, so the return type should be defined as ResultsObj .

public static ResultsObj doResults()
{
    ResultsObj newResults = new ResultsObj();
    newResults.resultsString = "Here is my string";

    return newResults;
}

Now your calling code knows that what is it getting back is a ResultsObj can can access the properties and methods of that type.

ResultsObj secondObj = doResults();
Console.WriteLine(secondObj.resultsString);

It all comes down to types . To reiterate, the compiler is only going to let you access properties and methods of the type defined by the reference variable.

BTW, you could also write the second block of code as:

var secondObj = doResults();
Console.WriteLine(secondObj.resultsString);

This may seem confusing, especially coming from a JavaScript background where var means something different. In this case C# is doing implicit typing . Because the method doResults() is defined as returning a ResultsObj the variable secondObj is implicitly typed as such. If you tried to write the following code it would not compile because the implicit typing already decided that secondObj was a ResultObj and you cannot assign a number to a variable of type ResultsObj .

var secondObj = doResults();
secondObj = 1; // This would cause a compiler error

No, using reflection is for sure not the most efficient way. But more important, it's also not the most readable way. Write compile-time type-safe code.

Instead of returning Object you should return the right type ResultsObj :

public static ResultsObj doResults()
{
    ResultsObj newResults = new ResultsObj();
    newResults.resultsString = "Here is my string";

    return newResults;
}

then it's easy, readable, safe and efficient:

ResultsObj secondObj = doResults();
string getString = secondObj.resultsString;

If you can't change the type and you have to use Object you can cast it to the right type:

object secondObj = doResults();
ResultsObj resultObj = (ResultsObj) secondObj;
string getString = resultObj.resultsString;

In C# we have type safety so use it whenever you can. So instead of returning an object , return the type you are using, for example:

public static ResultsObj doResults()
{
    ResultsObj newResults = new ResultsObj();
    newResults.resultsString = "Here is my string";

    return newResults;
}

Then you use it like this:

ResultsObj secondObj = doResults();
secondObj.resultsString = "blah";

Another alternative (and I only mention here because it can be useful in certain circumstances , so don't code like this by default) is to use the type dynamic . This removes all type checking but means you need to be careful about your code:

dynamic secondObj = doResults();
secondObj.resultsString = "blah"; //this will work
secondObj.NonExistantProperty = "blah"; //this will compile but fail at runtime

1.Return a ResultsObj and not just an object :

public static ResultsObj doResults()
{
    ResultsObj newResults = new ResultsObj();
    newResults.resultsString = "Here is my string";

    return newResults;
}

2.call the method with a correct left hand side:

ResultsObj res = doResults();
Console.Write(res.resultsString);

PS: The left hand side can be var(compiler feature) like in js:

var res = doResults(); 
Console.Write(res.resultsString);

Change:

public static object doResults()

to:

public static ResultsObj doResults()

then:

string getString = secondObj.resultsString;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM