Different payment details in a common list, to be casted I need to be able to access a number of different payment methods in a common list. They can be different methods - credit card, cheque, direct debit etc. The only common attributes are the payment method id and PaymentMethodEnum. I would then be casting the payment method to it's appropriate type to get the extended properties. Is this code arrangement the best way to achieve that?

Update:
I've added the enums. The usage for this is an MVC Website, and these payment details are effectively read only. The website shows different options based on the current payment method, and the other available methods that belong to a customer.

public class PaymentDetailBase
{
    public PaymentDetailBase(string id, PaymentMethodEnum paymentMethod)
    {
        this.Id = id;
        this.PaymentMethod = paymentMethod;
    }

    public string Id { get; }

    public PaymentMethodEnum PaymentMethod { get; }
}

public class CardDetail : PaymentDetailBase
{
    public CardDetail(string id, PaymentMethodEnum paymentMethod, string last4, DateTime expiry, PaymentCardTypeEnum cardType) : base(id, paymentMethod)
    {
        this.Last4 = last4;
        this.Expiry = expiry;
        this.CardType = cardType;
    }

    public string Last4 { get; }

    public DateTime Expiry { get; }

    public PaymentCardTypeEnum CardType { get; }
}

public class DirectDebitDetail : PaymentDetailBase
{
    public DirectDebitDetail(string id, PaymentMethodEnum paymentMethod, string accountName, string routingNumber, string bankAccount, DirectDebitAccountTypeEnum accountType) : base(id, paymentMethod)
    {
        this.AccountName = accountName;
        this.RoutingNumber = routingNumber;
        this.BankAccount = bankAccount;
        this.AccountType = accountType;
    }

    public string AccountName { get; }

    public string RoutingNumber { get; }

    public string BankAccount { get; }

    public DirectDebitAccountTypeEnum AccountType { get; }
}


[Flags]
public enum PaymentMethodEnum
{
    [Description("NONE")]
    None        = 0,

    [Description("Credit Card")]
    CreditCard  = 1 &lt;&lt; 0,

    [Description("Direct Debit")]
    DirectDebit = 1 &lt;&lt; 1,

    [Description("Check")]
    Cheque      = 1 &lt;&lt; 2,

    [Description("Invoice")]
    Invoice     = 1 &lt;&lt; 3,

    [Description("Money Order")]
    MoneyOrder  = 1 &lt;&lt; 4,

    [Description("Paper Invoice")]
    PaperInvoice = 1 &lt;&lt; 5
}

public enum PaymentCardTypeEnum
{
    [Description("Unknown")]
    Unknown,

    [Description("AMEX")]
    Amex,

    [Description("MASTERCARD")]
    MasterCard,

    [Description("DISCOVER")]
    Discover,

    [Description("VISA")]
    Visa
}

public enum BillingFrequencyEnum
{
    [Description("Unknown")]
    Unknown,

    [Description("Annual")]
    Annual,

    [Description("Semi-annual")]
    SemiAnnual,

    [Description("Quarterly")]
    Quarterly,

    [Description("Bi-monthy")]
    BiMonthly,

    [Description("Ten months")]
    TenMonths,

    [Description("Monthly")]
    Monthly
}

public enum DirectDebitAccountTypeEnum
{
    [Description("Unknown")]
    Unknown,

    [Description("Checking Account")]
    Checking,

    [Description("Savings Account")]
    Savings
}
I'm not in love with having an enum to know what base type to cast to.  If you want to stick to it then I'll give you a couple of pointers then later I'll give you a couple more options to think about

Make the base abstract and make the enum abstract

public abstract class PaymentDetailBase
{
    protected PaymentDetailBase(string id)
    {
        this.Id = id;
    }

    public string Id { get; }

    public abstract PaymentMethodEnum PaymentMethod { get; }
}


if you are going to cast based on the Enum then you don't want it being sent in the constructor.  What if I sent in the wrong enum for the type

Now classes the inherit from the base will be forced to fill in the type

public class CardDetail : PaymentDetailBase
{
    public CardDetail(string id, string last4, DateTime expiry, PaymentCardTypeEnum cardType) : base(id)
    {
        this.Last4 = last4;
        this.Expiry = expiry;
        this.CardType = cardType;
    }

    public string Last4 { get; }

    public DateTime Expiry { get; }

    public PaymentCardTypeEnum CardType { get; }

    public override PaymentMethodEnum PaymentMethod =&gt; PaymentMethodEnum.CreditCard;
}


I've worked with applications like this and I don't really care for the Enum.  It violates the open/close principle.  If I want another payment type I need to change the enum and some switch code that does hardcoded cast (yuck).   And what are you saving?  A switch statement instead of getting the base class and doing the AS statement and checking for null?  

Really when you run into this situation you need to think about your design.  What in the outside needs to know about those extended properties.  If everything then why cast to the base object in the first place just pass in the right class or you can try to make use of generics with constraints.  

Another option is if not a lot needs to know about the specific class then have the class do the operation you want done.  For Example you need to just copy over those properties to an entity.  Then aleave the base class abstract and make an abstract method like 

public void UpdateEntity(PaymentEntity entity);


now each class need to implement the update entity and it knows about it's own properties.