chincheta73
chincheta73

Reputation: 217

C# basic class definition with objects

This is a very C# basic question but I don't know how to google it, cause I don't know how this classes are called. I want to define a class (called ContactType) which has two objects: ContactType.Internal & ContactType.External. And each of this objects can be instantiated only once during the application, so every time I define the Type property of a contact as ContactType.External or ContactType.Internal, it is a reference to the same object.

Furthermore, this ContactType class, needs to override the method ToString(), so when the object ContactType.Internal needs to be parsed to string it returns "Contact of type Internal", and similar for the External Object.

Upvotes: 1

Views: 392

Answers (3)

Zesty
Zesty

Reputation: 3001

Your question wasn't clear, but I think what you're looking for is an enum.

From your description, I understand that your class is Contact. ContactType.External or ContactType.Internal is defined only once. And the property is Type. ToString() should return the static Description of the enum value that is stored in Type.

Class Definition

using System.ComponentModel;

public class Contact
{
    public enum ContactType
    {
        [Description("Contact of type External")]
        External = 1,
        [Description("Contact of type Internal")]
        Internal = 2
    }
    public ContactType Type { get; set; }

    public override string ToString()
    {
        return ((DescriptionAttribute)typeof(ContactType).GetMember(Type.ToString())[0].GetCustomAttributes(typeof(DescriptionAttribute), false)[0]).Description;
    }
}

Usage

    Contact myContact = new Contact();

    myContact.Type = Contact.ContactType.External;
    txtOutput.Text = myContact.ToString();
    //Output: "Contact of type External"

    myContact.Type = Contact.ContactType.Internal;
    txtOutput.Text = myContact.ToString();
    //Output: "Contact of type Internal"

Upvotes: 1

Sam
Sam

Reputation: 420

If I understand you correctly this basic principle should get you what you want. Important things to note are that the instances are static and can be accessed everywhere, and that the private constructor prevents any other code (barring reflection, you'll never prevent that) creating its own instances of ContactType.

sealed class ContactType
{
    public static ContactType Internal { get; } = new ContactType();
    public static ContactType External { get; } = new ContactType();

    private ContactType()
    {
    }
}

If you want more code involved in initialising the instances you may want to use a static constructor. This would look something like this:

sealed class ContactType
{
    public static ContactType Internal { get; }
    public static ContactType External { get; }

    private ContactType()
    {
    }

    static ContactType()
    {
        // More code can fit here if creating ContactType is complicated
        Internal = new ContactType();
        External = new ContactType(); 
    }
}

The static constructor will run once (right before the class is first used somewhere in your code) and set the static properties.

And here's an implementation that also handles the ToString() functionality:

sealed class ContactType
{
    private readonly string contactTypeName;

    public static ContactType Internal { get; } = new ContactType("Internal");
    public static ContactType External { get; } = new ContactType("External");

    private ContactType(string contactTypeName)
    {
        this.contactTypeName = contactTypeName;
    }

    public override string ToString()
    {
        // Note that these two ways of building this string are equivalent.
        // You may be more familiar with the old commented out way, but C# 6 added this new interpolation syntax.
        // Take your pick between the two, I prefer the interpolation.

        //return "Contact of type " + this.ContactTypeName;
        return $"Contact of type {this.contactTypeName}";
    }
}

Upvotes: 1

John Wu
John Wu

Reputation: 52280

The old way of doing this would have been to use a static variable or a Singleton design pattern. And you can still do it that way. But those static members are terribly difficult to isolate out when writing unit tests.

For this reason, the more modern way to deal with this issue would be use Dependency Injection with something like InstancePerLifetimeScope. That way your object factory will always spit out the same instance of the Internal and External objects no matter how many times the code tries to create them.

Upvotes: 0

Related Questions