Is Passing a C++ Object into Its Own Constructor Legal

Passing object of class in constructor of the same class

You can add another constructor in which you supply values manually:

public Student(int id, string name)
{
StudentId = id;
Name = name;
}

The reason your initial code doesn't work is, when you are creating an object that needs another instance of the same type, the dependency chain goes up to infinity and you can never have a start point.

By having a manual constructor, you can manually create a start point, in other words, an initial object that other objects can depend on. Therefore you eliminate infinite dependency chain.

c# passing class argument to constructor

I would change the definition of PropertyClass to

public class PropertyClass<T>
{
public List<T> Settings { get; set; }

public PropertyClass()
{
Settings = new List<T>();
}

public void SaveXml(string fileName)
{
using (FileStream stream = new FileStream(fileName, FileMode.Create))
{
XmlSerializer XML = new XmlSerializer(typeof(List<T>), new XmlRootAttribute("Settings"));

XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);

XML.Serialize(stream, Settings, namespaces);
}
}
}

The type parameter T specifies the type of the items in the List<T>, so that you can instantiate PropertyClass as follows

var pc = new PropertyClass<MyProperty>();

Or when you get tired of MyProperty you can change it to new PropertyClass<foo>() without changing it elsewhere.

Another nice feature that I like about generics is that you can actually place constraints on the type parameter in the line where you declare it like:

public class PropertyClass<T> where T : MyClass, IMyInterface, new()

This means that T has to be derived from MyClass, it has to implement IMyInterface and has to have a parameterless constructor. (Obviously you do not need to add all such constraints, but they can all be useful in certain cases).

I want to rant a little more, but I am sure you can play with it and find some uses for it.

Why can't a member method be passed to a base class constructor?

Rewrite it like this:

public MuteFlarg() : base(this.GiveDumbLook) { }

and it is now clear why you can't. It's not legal to refer to this in a base class constructor invocation. This is not legal because it can easily lead to bugs. The constructor for the derived class has not run yet, and so the fields are not set to their initial state (initial state being defined by the state of the object when the constructor is done running).

This is explicitly stated in §10.11.1 of the specification:

An instance constructor initializer cannot access the instance being created. Therefore it is a compile-time error to reference this in an argument expression of the constructor initializer, as is it a compile-time error for an argument expression to reference any instance member through a simple-name.

The last statement explicitly forbids referring to this.GiveDumbLook by its simple-name GiveDumbLook.

Can I pass arguments to a base constructor from a derived class's default constructor?

Yes, you can do this if you make the arrays static:

public class EuchreDeck : Deck
{
private static readonly string[] values = new string[] { "9", "10", "J", "Q", "K", "A" };
private static readonly string[] suits = new string[] { "clubs", "spades", "hearts", "diamonds" };

public EuchreDeck() : base(values, suits)
{

}
}

The reason why you can't use it as you had with instance-level members is because it's not legal to do so. This comes from the C# specification 10.10.1 Constructor Initializers where it states:

An instance constructor initializer cannot access the instance being
created. Therefore it is a compile-time error to reference this in an
argument expression of the constructor initializer, as is it a
compile-time error for an argument expression to reference any
instance member through a simple-name.

By switching the arrays to be static, they are no longer accessed via the instance but rather by the EuchreDeck type.


That said, I might suggest you take a slight tweak on the design. Maybe use a factory to create these specialized decks for you rather than their constructors.

As an example, maybe refactor something like this:

Change your base Deck to just take the set of cards:

public abstract class Deck
{
public List<Card> Cards;
protected Deck(IEnumerable<Card> cards)
{
this.Cards = new List<Card>(cards);
}
}

Then have the factory setup like this:

public class EuchreDeck : Deck
{
private EuchreDeck(IEnumerable<Card> cards) : base(cards)
{

}

public class Factory : DeckFactory
{
private static readonly string[] Values = new string[] { "9", "10", "J", "Q", "K", "A" };
private static readonly string[] Suits = new string[] { "clubs", "spades", "hearts", "diamonds" };

public static EuchreDeck Create()
{
var cards = CreateCards(Values, Suits);
return new EuchreDeck(cards);
}
}
}

Instantiation/usage as:

EuchreDeck.Factory.Create();

You could play around with the factory usage. I just nested it in the class so you couldn't create a EuchreDeck with an invalid set of cards. Your DeckFactory base would have your conversion method (which looks like you currently have in your Deck constructor)

Beyond that, I'm not sure if you have a specific need for a EuchreDeck; I'm assuming you have other methods associated with it? If not, you could probably ditch the class altogether and just let the factory create a Deck with the needed cards.

How are IDisposable objects passed to base constructor arguments handled in C# if initialization fails?

Not really an answer to the question, but...

You don't necessarily need to disable the rule altogether - you can suppress it for the methods where you know that the analysis is over-zealous:

[SuppressMessage("Microsoft.Reliability",
"CA2000:DisposeObjectsBeforeLosingScope",
Justification = "Your reasons go here")]
public YourClass(IDisposable obj) : base(obj)
{
}

Although the CA2000 analysis is so broken that it might be more useful to disable it altogether.

What is the preferred way of constructing objects in C#? Constructor parameters or properties?

The preferred way depends on your design.

Constructor properties are for items that your object requires in order to be correctly constructed. That is to say, any properties the object should have in order to be initialized need to be in the constructor (you don't usually want a partially intialized object after the constructor is called unless you're creating a factory or builder pattern and the constructor is hidden from all but the factory/builder).

Property intializers are best for additional configuration after a constructor that is required by your particular use case but is not required for the object to be considered initialised.

For example, you could have an object that represents a person. A person needs a name and an age to be initialised, but the address they live at is an optional configuration. So, the name and age are constructor parameters, and the address is a read/write property.

Person johnDoe = new Person("John Doe", 24) { Address = "42 Adams Street" };

C# Ways to access containing class without passing reference

I understand your pain. I've been there too. But the answer is no in a standard way of programming. It maybe possible by using the call stack, reflection and some hack work, but since you are trying to simplify your code, you don't want to have that kind of stuff in your code.

Pass current object type into base constructor call

Ah Hah! I found a solution. You can do it with generics:

public abstract class VeryBaseClass
{
public VeryBaseClass(string className, MyObject myObject)
{
this.ClassName = className;
}

public string ClassName{ get; set; }
}
public abstract class BaseClass<T> : VeryBaseClass
{
public BaseClass(MyObject myObject)
: base(typeof(T).Name, myObject)
{
}
}

public class InheritedClass : BaseClass<InheritedClass>
{
public InheritedClass(MyObject myObject)
: base(myObject)
{

}
}

Passing this to base constructor

No, you can't use this in a constructor initializer. You'd have to add call Add(this) afterwards - but you can do that in the Base<TSelf> constructor, so long as you cast to TSelf. You need to cast this to object first before casting to TSelf for fairly complicated reasons around the conversions allowed with type parameters, unfortunately.

You can create a List<TSelf> in the Base constructor though, with no problem. Here's sample code showing both of these:

abstract class Base<TSelf>
{
// Let's make it a property rather than a public field...
public ICollection<TSelf> List { get; }

public Base()
{
List = new List<TSelf>();
// This will obviously fail if you try to create a `Base<Foo>`
// from a class that isn't a Foo
TSelf selfThis = (TSelf) (object) this;
List.Add(selfThis);
}
}

class Implementation : Base<Implementation>
{
}

You can add a constraint to TSelf to make the casting failure less likely accidentally but not impossible:

abstract class Base<TSelf> where TSelf : Base<TSelf>

That doesn't stop you from writing

class Implementation : Base<Implementation> {}
class Evil : Base<Implementation> {}

Then when you construct an instance of Evil, you're trying to add an Evil reference to a List<Implementation> which can't work... and the cast fails to stop you from getting that far.



Related Topics



Leave a reply



Submit