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
Why Does Poll Keep Returning Although There Is No Input
What Is Shared_Ptr's Aliasing Constructor For
Extending the C++ Standard Library by Inheritance
Force Gcc to Notify About Undefined References in Shared Libraries
Difference Between *(Pointer + Index) and Pointer[]
Porting Clock_Gettime to Windows
Convert Mat to Array/Vector in Opencv
Why Use Functors Over Functions
How to Read a Binary File into a Vector of Unsigned Chars
Concatenate Two String Literals
Redirect Stdout/Stderr to a String
How Do Sizeof(Arr)/Sizeof(Arr[0]) Work
How to Use C++ Classes with Ctypes
How to Simulate "Press Any Key to Continue"
Difference Between Char* and Char[]
What Is the Performance Penalty of C++11 Thread_Local Variables in Gcc 4.8
Error Lnk2019: Unresolved External Symbol _Main Referenced in Function _Tmaincrtstartup