tags:

views:

72

answers:

4

Hello, guys!

I have some code:

public class class1
{
    public class1(int count)
    {
         // count must be 4,6,8
    }
}

That class 'class1' is a public class in my SDk library which I write. Count variable is a very important for class1. It must be either 4,6,8.

I want to ensure that programmer (used my SDK) can't create an instance of class1 with an invalid 'count' parameter.

What should I do? What do you recommend me to do?

Is it good to use enumeration here ?

+2  A: 

An enumeration is good for discovery but won't help you with validation - you can still pass in incorrect values.

new class1(FooCount.Four);  // Using an enum allows you to write this.
new class1((FooCount)5);    // But you can also do this.

To validate the value (whether you choose to use an enumeration or not) check the value against the list of allowed values and raise an ArgumentException if it is an invalid value.

Mark Byers
Though if 4, 6,and 8 have concrete values that mean something, an enumeration might not be the worst idea, it just won't protect you from anything...
Dave Markle
@Mark, I thought about argumentexception. But maybe there's a better design - some pattern for example ... @Dave, you can cheat with enumerations ...
Alexander Dronov
@Alexander Dronov: You could look into code contracts: http://social.msdn.microsoft.com/Forums/en/codecontracts/thread/f85fad00-86f9-420e-bcd3-16a066c6a401
Mark Byers
@Mark, thanks for a link. I read it right now
Alexander Dronov
A: 

What about abstracting class1 and create concrete implementation for each count. Make the class1 constructor portected and you're protected. Just an idea.

Adrian Godong
@Adrian, i thought about that implementation. But it will lead to several public classes in SDK --> big SDk --> not so good solution. I am trying to find an alternative solution.
Alexander Dronov
+1  A: 

If you don't want to use exceptions there is always the Factory pattern. You request a Class1 with a certain parameter, the Factory validates it and returns a null object if validation fails.

There are probably other better solutions that are not so generic. Off the top of my head, having 3 types of derived classes: ClassCount4, ClassCount5, etc. could be a solution.

Can you give some more information on why it is important that Count be a specific value?

EDIT:

You can try something like this:

class Class1
{
    private int _count;

    Class1(int Count)
    {
        _count = Count;
    }

    public static Class1 Instance (int Count)
    {
        if (ValidParam(Count))
            return new Class1(Count);
        return null;
    }

    private static bool ValidParam(int Count)
    {
        if ( Count == 4 || Count == 6 || Count == 8 )
            return true;
        return false;
    }
}
Andrei
@andreit, count is a size of game field. 4x4, 6x6, 8x8. All other methods and properties of class1 relies(?) on it.
Alexander Dronov
A: 

Rather than having class1 take in the variable count, why not create three classes with a common base class?

public abstract class Class1Base
{
    protected class1(int count) { }
}

public class Class1Count4
{
    public Class1Count4()
        : base(4)
    { }
}

// also have implementations for the other eligible values for count.

If your algorithm actually changes based off of what count is (i.e. there is no common code between the separate usages of count), then you can use an interface instead:

public interface IClass1
{
    // Interface methods
}

public class CountImpl4 : IClass1
{
    // Implement IClass1 with count being 4.
}

// Other implementations.

With either of these designs you then take the possibility of invalid user input out of the equation. Plus, if you ever need to change how one implementation works, need to support other count values, etc. you can just extend Class1Base / implement IClass1 with another class.

Edit

Since you wish to keep this within one class, why not define Type-Safe enumeration to pass in?

public struct CountEnum
{
    public readonly int Count;

    public static readonly CountEnum Four = new CountEnum(4);
    public static readonly CountEnum Six = new CountEnum(6);
    public static readonly CountEnum Eight = new CountEnum(8);

    private CountEnum(int count)
    {
        Count = count;
    }
}

public class Class1
{
    public Class1(CountEnum countEnum)
    { 
        // Access the value via countEnum.Count.
    }
}

Since CountEnum only has a single private constructor, the only available instances are the statically-defined Four, Six, and Eight. The user can now only enter Four, Six, or Eight. Since CountEnum is a struct, null is not available either.

Secret Agent Man
@S. DePouw, i thought about that implementation. But it will lead to several public classes in SDK --> big SDk --> not so good solution. I am trying to find an alternative solution.
Alexander Dronov