8

I'm a PHP programmer for some time. Two days ago, I went to a job interview where they gave me an assigment to do in ASP.NET ( C# ). I would really like to get out of the php sphere of influence and learn a decent language that can challenge me. So, I have a question

Do all instances have to be instantiated at runtime? In php, I can do something like this...

class SomeObject {}

$objString = "SomeObject";
$objInstance = new $objString();

I can't do that in C#, probably beacuse it's a compiled language. In C#, would I have to create a Factory pattern who will instantiate objects. That would also mean that if I have to instantiate 10 object in that Factory, that there would be 10 if statements which is ugly.

I found Activator object with its Activator::createInstance() method but I could't get it to work. Also there's Reflection, but both of these ( as I'm aware of ) are a performance impact.

So, is there a way to dynamicly create objects or could it be that in C#, i can immediatlly create all objects that my program will use, which is really tempting?

EDIT

Ok, so let's say that I have 5 object that are used in 5 different occassions. I run the program, the program evaluates that it needs one of those object and instantiates it. The other four are never instantiated. I close the program.

Second time, I run the program with different parameters, and 2 of those 5 objects are created, other three never came into existence.

This is easy in PHP. Let's put Activator and other tools aside, is it good practice in C# world to create all the 5 objects when I know that maybe, only one of them will be used?

Mario Legenda
  • 749
  • 1
  • 11
  • 24
  • 3
    I don't know PHP, but in C# you can create an object and initialize it at the same time. You don't need to use a factory or the `Activator` object - simply `SomeObject someObj = new SomeObject();` will do. – Tim Oct 30 '14 at 07:42
  • 10
    Constructing objects dynamically like this is possible in .NET, but you should learn the whole language, runtime, platform, and not just the syntax. What I mean is that if you try to keep programming as you did in PHP in C#, you're going to have a very bad experience. – Lasse V. Karlsen Oct 30 '14 at 07:52
  • "Do all instances have to be instantiated at runtime?". Well no, I mean, they aren't instantiated compile-time or coffee-time if you mean that... but you don't _have_ to instantiate any of them. (And you certainly don't have to use reflection if you don't want to). – atlaste Oct 30 '14 at 07:54
  • I don't know php all that well but you should really look into how you are attempting to use it.. because after all, you are creating it to do something with it which means you must be needing to use its values somewhere? Sounds like you may want to use generics or interfaces or you are really asking an XY problem where a good answer would rely on the specifics – Sayse Oct 30 '14 at 08:03
  • Let's say I have 1 object out of a pool of 5 objects that are to be created on a changing value of a string. That would mean that I would have 5 `if` statements ( or case or whatever ) that would then create the desired object. Is that desirable? – Mario Legenda Oct 30 '14 at 08:04
  • see my updated answer, hope this helps a little – nozzleman Oct 30 '14 at 08:09
  • @MarioLegenda - Again, how do you plan on using these objects after they are created though? do they each go off on their own code tangent or are you expected to use them in the same way(i.e do they share similar params)? – Sayse Oct 30 '14 at 08:43
  • In reality, I have 3 objects that share the same interface and only one of them has to be instantiated when certain conditions are met. The fact that I have 3, doesn't make any diffrence. I could have had 1000. – Mario Legenda Oct 30 '14 at 08:49
  • I'd like to point out that there is a Code Review Stack Exchange where you can have experts evaluate whether your code is a good way of using C#. Point out that you have a PHP background and they'll look for common misconceptions. – usr Oct 30 '14 at 14:30
  • Per your example of instantiating an object based on a string: Can you? Yes. It's called reflection. Should you? Almost certainly not. The use cases for reflection are few and far between. C# is plenty powerful enough to do anything you want to do, but you need to learn how things are done in C#. (In other words, don't learn how to program PHP code in C#.) – riwalk Oct 30 '14 at 18:13

4 Answers4

6

I don't know if i got your question wrong, but creating object of your given class SomeObject in C# is as easy as the following:

var obj = new SomeObject();

Using the Activator-Class it should look sth. like one of the following

var obj2 = Activator.CreateInstance(typeof(SomeObject)); 
var obj3 = Activator.CreateInstance<SomeObject>();`

var someObjType = Type.GetType("SomeObject");  // if you have to use a string
var obj4 = Activator.CreateInstance(someObjType);

Note that using the Activator-Class for instanciating objects isn't necessary in most cases. The first example is the standard way if you know the Type of the Class at compiletime.

UPDATE

regarding your update, since i don't know the details what comes to my mind is lazy instanciation. Since everything, including the entry point of your application is an object in C#, you can solve the issue using properies with backed fields like in the following example

class Program
{
    // backing fields
    private SomeObject obj1;
    private SomeObject obj2;
    private SomeObject obj3;
    private SomeObject obj4;
    private SomeObject obj5;

    // this way, obj1 only gets instanciated when needed
    public SomeObject Obj1 
    {
        get
        {
            if (obj1 == null)
            { 
                 obj1 = new SomeObject(); 
            }
            return obj1;
        }
    }

    // same for the other objects

    [...]

}

I you are concerned about the memory usage of your object, i recommend you to learn about how to properly implement IDisposable

UPDATE 2

To provide the possibility recommended in the comments by @ Mad Sorcerer, you could back the fields using the Lazy-Class which takes some effort of your shoulder, the effect is quite the same as in the previous update.

class Program
{
    // Lazy backing fields
    private Lazy<SomeObject> obj1 = new Lazy<SomeObject>();
    private Lazy<SomeObject> obj2 = new Lazy<SomeObject>();
    private Lazy<SomeObject> obj3 = new Lazy<SomeObject>();
    private Lazy<SomeObject> obj4 = new Lazy<SomeObject>();
    private Lazy<SomeObject> obj5 = new Lazy<SomeObject>();

    // this way, obj1 only gets instanciated when needed
    public SomeObject Obj1 
    {
        get { return obj1.Value; }
    }

    // same for the other objects

    [...]

}
nozzleman
  • 9,529
  • 4
  • 37
  • 58
  • Yea, thanks. All of the answers on this question basiclly told me that I should stop thinking in PHP and start thinking like C#. I mean, I've been learning C# for about one and a half day and experience comes with time, right? – Mario Legenda Oct 30 '14 at 08:13
  • I made an article sized question when i could just ask "Is there a way to lazy instantiate an object in C#?" and that would be it. Not smart on my side! Thank you very much. – Mario Legenda Oct 30 '14 at 08:22
  • @MadSorcerer thanks for the suggestion, in included it in the answer – nozzleman Oct 30 '14 at 08:53
  • @MarioLegenda most PHP devs have bad habits when it comes to development (no offense to anyone intended). In PHP it is possible to make classes and call methods in similar fashion to C#, but it is uncommon to see those practices in the PHP community. The reason you want to type out a declarative object and not dynamic is to make the code clearer down the road. Thinking "where did this come from" usually isn't ideal when reading code a year later. Not to say PHP is bad, but there is a reason for FaceBook's HACK programming language and a reason dynamic objects are not ideal. – vipero07 Jun 19 '15 at 16:03
5

Yes, you can create objects dynamically in C#. But not as easily as in PHP.

As you found, there's Activator. It works fine when you use it correctly. :) There's also direct reflection (Activator is based on reflection as well). Both are slow when used naively.

Using the Expression type, it is possible to cache the logic for instantiating an object. It's still slow the first time, but if you expect to be creating the same type of object repeatedly, this approach works well (and if you don't, then the fact that it's slow via Activator doesn't matter :) ).

That said, most of the time you should not need to create objects dynamically like in your example. The strong, compile-time type-checking in C# should be taken advantage of, not eschewed. Writing code that instantiates objects for which the type is already known at compile time is most efficient, and most type-safe.

For those relatively few times where you do need dynamic behavior, it is possible.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
2

So that PHP code... you're choosing which class to instantiate by it's name as a string?

You need to look up the type first and then instantiate it with Activator.

Type classType = Type.GetType("SomeObject");
object instance = Activator.CreateInstance(classType);

You can look up it's constructor and call that instead using reflection which looks more like this

Type classType = Type.GetType("SomeObject");
var ctorInfo = classType.GetConstructor(Type.EmptyTypes);
object instance = ctorInfo.Invoke(new object[] {});

and you can cache the constructor as a delegate which eliminates the performance penalty which comes from looking up stuff#

Note that Type.GetType has some issues of it's own. The above code will work if SomeObject is in the System namespace. You may need to add the namespace, class and sometime assembly. In all it's safest to use the AssemblyQualifiedName.

James
  • 9,774
  • 5
  • 34
  • 58
  • It can be not obvious for a novice, if `SomeObject` class is scoped within some namespace like `ConsoleApplication1` it should be explicitly shown: `GetType("ConsoleApplication1.SomeObject");` – Diligent Key Presser Oct 30 '14 at 07:59
1

There are a few ways to create an instance of a class in C#.

The usual way is simply to use new:

MyType myInstance = new MyType();

For dynamically creating objects, based on their name for instance, Activator.Createinstance() works, but you must know the assembly where that class is defined so you can correctly create that instance.

However, especially if you are just beginning, I wouldn't bother with getting into this yet.
C# is a statically-typed language, meaning that resolution of type is made during compilation.

On top of that, consider that the IDE, Visual Studio, will help you tremendously since it can scan files in your project and know the Type of each of members you are typing in your code.

Statically-types languages are helpful in avoiding the exact sort of issues that arise in purely dynamic languages: they force you to be coherent, at the expense of requiring you to be explicit in your declaration (although C#, with the var keyword, can help a lot in avoiding that normally required verbosity).

So the whole point is to make sure that you declare all types your will need in your application.

If you need a particular class member to accept data from multiple other classes, you can use inheritance, creating a base class that others will inherit some behaviour from, or use Interfaces, to describe common members to a variety of types. Each has its advantages and drawbacks.

If you are dabbling with C#, just experimenting, I'd recommend getting LINQpad. It may help you experiment while learning.

I would also stay away from anything that's not canonical: understand idiomatic C# first before you go too deep in trying to do do runtime stuff.

One area you can explore though, is the dynamic type. It's not as flexible as what you'd expect from a truly dynamic language, but it's a way to deal with type-uncertainty.
It has a performance drawback though, and should be avoided if you want to benefit from Intellisense in Visual Studio and want to benefit from the normal type-checking that the IDE and compiler can provide for you.

Community
  • 1
  • 1
Renaud Bompuis
  • 16,596
  • 4
  • 56
  • 86
  • I asked this question up there so I'll just copy/paste it to you. Let's say I have 1 object out of a pool of 5 objects that are to be created on a changing value of a string. That would mean that I would have 5 if statements ( or case or whatever ) that would then create the desired object. Is that desirable and a normal practice in C#? – Mario Legenda Oct 30 '14 at 08:09