175

I have this API function:

public ResultEnum DoSomeAction(string a, string b, DateTime c, OtherEnum d, 
     string e, string f, out Guid code)

I don't like it. Because parameter order becomes unnecessarily significant. It becomes harder to add new fields. It's harder to see what's being passed around. It's harder to refactor method into smaller parts because it creates another overhead of passing all the parameters in sub functions. Code is harder to read.

I came up with the most obvious idea: have an object encapsulating the data and pass it around instead of passing each parameter one by one. Here is what I came up with:

public class DoSomeActionParameters
{
    public string A;
    public string B;
    public DateTime C;
    public OtherEnum D;
    public string E;
    public string F;        
}

That reduced my API declaration to:

public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code)

Nice. Looks very innocent but we actually introduced a huge change: we introduced mutability. Because what we previously had been doing was actually to pass an anonymous immutable object: function parameters on stack. Now we created a new class which is very mutable. We created the ability to manipulate the state of the caller. That sucks. Now I want my object immutable, what do I do?

public class DoSomeActionParameters
{
    public string A { get; private set; }
    public string B { get; private set; }
    public DateTime C { get; private set; }
    public OtherEnum D { get; private set; }
    public string E { get; private set; }
    public string F { get; private set; }        

    public DoSomeActionParameters(string a, string b, DateTime c, OtherEnum d, 
     string e, string f)
    {
        this.A = a;
        this.B = b;
        // ... tears erased the text here
    }
}

As you can see I actually re-created my original problem: too many parameters. It's obvious that that's not the way to go. What am I going to do? The last option to achieve such immutability is to use a "readonly" struct like this:

public struct DoSomeActionParameters
{
    public readonly string A;
    public readonly string B;
    public readonly DateTime C;
    public readonly OtherEnum D;
    public readonly string E;
    public readonly string F;        
}

That allows us to avoid constructors with too many parameters and achieve immutability. Actually it fixes all the problems (parameter ordering etc). Yet:

That's when I got confused and decided to write this question: What's the most straightforward way in C# to avoid "too many parameters" problem without introducing mutability? Is it possible to use a readonly struct for that purpose and yet not have a bad API design?

CLARIFICATIONS:

  • Please assume there is no violation of single responsibiltiy principle. In my original case the function just writes given parameters to a single DB record.
  • I'm not seeking a specific solution to the given function. I'm seeking a generalized approach to such problems. I'm specifically interested in solving "too many parameters" problem without introducing mutability or a terrible design.

UPDATE

The answers provided here have different advantages/disadvantages. Therefore I'd like to convert this to a community wiki. I think each answer with code sample and Pros/Cons would make a good guide for similar problems in the future. I'm now trying to find out how to do it.

14
  • Clean Code: A Handbook of Agile Software Craftsmanship by Robert C. Martin and Martin Fowler's Refactoring book covers this a bit Commented Jun 4, 2011 at 21:32
  • 1
    Isn't that Builder-solution redundant if you use C# 4 where you have optional parameters?
    – khellang
    Commented Jun 4, 2011 at 22:06
  • 1
    I might be stupid, but I fail to see how this is a problem, considering that the DoSomeActionParameters is a throwaway object, which will be discarded after the method call.
    – Vilx-
    Commented Jun 5, 2011 at 1:05
  • 6
    Note that I'm not saying that you should avoid readonly fields in a struct; immutable structs are a best practice and readonly fields help you create self-documenting immutable structs. My point is that you should not rely upon readonly fields being observed to never change, because that is not a guarantee that a readonly field gives you in a struct. This is a specific case of the more general advice that you should not treat value types as though they are reference types; they are a very different animal. Commented Jun 7, 2011 at 6:18
  • 7
    @ssg: I'd love that too. We have added features to C# that promote immutability (like LINQ) at the same time as we've added features that promote mutability (like object initializers.) It would be nice to have a better syntax to promote immutable types. We're thinking hard about it and have some interesting ideas, but I wouldn't expect any such thing for the next version. Commented Jun 7, 2011 at 15:00

13 Answers 13

94

Use a combination of builder and domain-specific-language style API--Fluent Interface. The API is a little more verbose but with intellisense it's very quick to type out and easy to understand.

public class Param
{
        public string A { get; private set; }
        public string B { get; private set; }
        public string C { get; private set; }


  public class Builder
  {
        private string a;
        private string b;
        private string c;

        public Builder WithA(string value)
        {
              a = value;
              return this;
        }

        public Builder WithB(string value)
        {
              b = value;
              return this;
        }

        public Builder WithC(string value)
        {
              c = value;
              return this;
        }

        public Param Build()
        {
              return new Param { A = a, B = b, C = c };
        }
  }


  DoSomeAction(new Param.Builder()
        .WithA("a")
        .WithB("b")
        .WithC("c")
        .Build());
7
  • +1 -- this kind of approach (which I've commonly seen called a "fluent interface") is exactly what I had in mind as well. Commented Jun 4, 2011 at 23:57
  • +1 -- this is what I ended up in the same situation. Except that there was just one class, and DoSomeAction was a method of it.
    – Vilx-
    Commented Jun 5, 2011 at 0:54
  • +1 I too thought of this, but since I am new to fluent interfaces, I didn't know if it was a perfect fit here. Thanks for validating my own intuition.
    – Matt
    Commented Jun 5, 2011 at 22:31
  • 1
    @ssg, it is common in these scenarios. The BCL has connection string builder classes, for example. Commented Jun 7, 2011 at 11:00
  • 1
    This approach looks good but it seems you can't enforce the caller to specify all parameters, while with constructor you can. e.g. you can skip WithC(string) even C is required.
    – joe
    Commented Apr 22, 2021 at 9:25
27

One style embraced in the frameworks is usually like grouping related parameters into related classes (but yet again problematic with mutability):

var request = new HttpWebRequest(a, b);
var service = new RestService(request, c, d, e);
var client = new RestClient(service, f, g);
var resource = client.RequestRestResource(); // O params after 3 objects
5
  • Condensing all the strings into a string array only makes sense if they're all related. From the order of arguments, it looks like they're not all completely related.
    – icktoofay
    Commented Jun 4, 2011 at 21:16
  • Agreed, besides, that would only work if you have a lot of the same types as parameter. Commented Jun 4, 2011 at 21:19
  • How is that different than my first example in the question? Commented Jun 4, 2011 at 21:54
  • Well this is the usual embraced style even in the .NET Framework, indicating that your first example is quite right in what it's doing even it introduces minor mutability issues (though this example is from another library obviously). Nice question by the way. Commented Jun 4, 2011 at 21:56
  • 2
    I have been converging to this style more over time. Apparently significant amount of the "too many parameters" issues can be resolved with good logical groups and abstractions. In the end it makes the code more readable and more modularized. Commented Apr 23, 2013 at 15:01
13

Just change your parameter data structure from a class to a struct and you’re good to go.

public struct DoSomeActionParameters 
{
   public string A;
   public string B;
   public DateTime C;
   public OtherEnum D;
   public string E;
   public string F;
}

public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code) 

The method will now get its own copy of the structure. Changes made to the argument variable cannot be observed by the method, and changes the method makes to the variable can not be observed by the caller. Isolation is achieved without immutability.

Pros:

  • Easiest to implement
  • Least change of behavior in underlying mechanics

Cons:

  • Immutability is not obvious, requires developer attention.
  • Unnecessary copying to maintain immutability
  • Occupies stack space
7
  • +1 That's true but doesn't solve the part about "exposing fields directly is evil". I'm not sure how bad things could get worse if I opt for using fields instead of properties on that API. Commented Jun 7, 2011 at 14:13
  • 1
    @ssg - So make them public properties instead of fields. If you treat this as a struct that will never have code, then it doesn't make a lot of difference whether you use properties or fields. If you decide to ever give it code (such as validation or something), then you will definitely want to make them properties. At least with public fields, nobody will ever have any illusions about invariants existing on this strucuture. It will have to be validated by the method exactly like parameters would have been. Commented Jun 7, 2011 at 14:23
  • 10
    I think that the exposing-fields-is-evil rule applies to objects in an object-oriented design. The struct that I am proposing is just a bare-metal container of parameters. Since your instincts were to go with something immutable, I think that such a basic container might be appropriate for this occasion. Commented Jun 7, 2011 at 14:28
  • Well even if there is a problem, all disadvantages could be avoided with a simple replace operation as you said. I'll give this a shot and see how it lays out. Commented Jun 7, 2011 at 14:45
  • 2
    @JeffreyLWhitledge: I really dislike the idea that exposed-field structs are evil. Such a claim strikes me as being equivalent to saying that screwdrivers are evil and people should use hammers because the points of screwdrivers dent nail heads. If one needs to drive a nail, one should use a hammer, but if one needs to drive a screw, one should use a screwdriver. There are many situations where an exposed-field struct is precisely the right tool for the job. Incidentally, there are far fewer where a struct with get/set properties is really the right tool (in most cases where...
    – supercat
    Commented Sep 25, 2012 at 22:21
11

What you have there is a pretty sure indication that the class in question is violating the Single Responsibility Principle because it has too many dependencies. Look for ways to refactor those dependencies into clusters of Facade Dependencies.

16
  • 1
    I'd still refactor by introducing one or more parameter objects, but obviously, if you move all arguments to a single immutable type, you've accomplished nothing. The trick is to look for clusters of arguments that are more closely related, and then refactor each of those clusters to a separate parameter object. Commented Jun 4, 2011 at 21:33
  • 2
    You can turn each group into an immutable object in itself. Each object would only need to take a few parameters, so while the actual number of arguments remains the same, the number of arguments used in any single constructor will be reduced. Commented Jun 4, 2011 at 22:49
  • 2
    +1 @ssg: Every time I've ever managed to convince myself of something like this, I've proved myself wrong over time by driving useful abstraction out of big methods requiring this level of parameters. The DDD book by Evans may give you some ideas on how to think about this (though your system sounds like it's potentially a far from relevant place to the application of such patters) - (and it's just a great book either way). Commented Jun 7, 2011 at 8:27
  • 3
    @Ruben: No sane book would say "in a good OO design a class should not have more than 5 properties". Classes are grouped logically and that kind of contextualization cannot be based on quantities. However C#'s immutability support starts creating problems at a certain number of properties before we start violating good OO design principles. Commented Jun 7, 2011 at 8:59
  • 3
    @Ruben: I didn't judge your knowledge, attitude or temper. I expect you to do the same. I'm not saying your recommendations are not good. I'm saying that my problem can appear even on the most perfect design and that seems to be an overlooked point here. Although I understand why experienced people ask fundamental questions about the most common mistakes, it gets less enjoyable to clarify it after a couple of rounds. I must again say that it's very possible to have that problem with a perfect design. And thanks for the upvote! Commented Jun 7, 2011 at 13:39
7

I'm not a C# programmer but I believe C# supports named arguments: (F# does and C# is largely feature compatable for that sort of thing) It does: http://msdn.microsoft.com/en-us/library/dd264739.aspx#Y342

So calling your original code becomes:

public ResultEnum DoSomeAction( 
 e:"bar", 
 a: "foo", 
 c: today(), 
 b:"sad", 
 d: Red,
 f:"penguins")

this takes no more space/thought that your object creation and has all the benifits, of the fact that you haven't changed what is happening in the unerlying system at all. You don't even have to recode anything to indicate the arguments are named

Edit: here is a artical i found about it. http://www.globalnerdy.com/2009/03/12/default-and-named-parameters-in-c-40-sith-lord-in-training/ I should mention C# 4.0 supports named arguments, 3.0 did not

1
  • An improvement indeed. But this only solves code readability and it only does that when the developer opts-in for using named parameters. It's easy for one to forget to specify names and give away the benefits. It does not help when writing the code itself. e.g. when refactoring the function into smaller ones and pass the data around in a single contained packet. Commented Jun 5, 2011 at 10:18
7

Why not just make an interface that enforces immutability (i.e. only getters)?

It's essentially your first solution, but you force the function to use the interface to access the parameter.

public interface IDoSomeActionParameters
{
    string A { get; }
    string B { get; }
    DateTime C { get; }
    OtherEnum D { get; }
    string E { get; }
    string F { get; }              
}

public class DoSomeActionParameters: IDoSomeActionParameters
{
    public string A { get; set; }
    public string B { get; set; }
    public DateTime C { get; set; }
    public OtherEnum D { get; set; }
    public string E { get; set; }
    public string F { get; set; }        
}

and the function declaration becomes:

public ResultEnum DoSomeAction(IDoSomeActionParameters parameters, out Guid code)

Pros:

  • Doesn't have stack space problem like struct solution
  • Natural solution using language semantics
  • Immutability is obvious
  • Flexible (consumer can use a different class if he wants)

Cons:

  • Some repetitive work (same declarations in two different entities)
  • Developer has to guess that DoSomeActionParameters is a class that could be mapped to IDoSomeActionParameters
4
  • +1 I don't know why I didn't think of that? :) I guess I thought object would still suffer from a constructor with too many parameters but that's not the case. Yes that's a very valid solution too. The only problem I can think of is it's not really straightforward for API user to find the right class name that supports given interface. Solution that requires the least documentation is better. Commented Jun 5, 2011 at 10:28
  • I like this one, the duplication and knowledge of the map are handled with resharper, and I can supply default values using the default constructor of the concrete class Commented Sep 16, 2012 at 14:43
  • 3
    I don't like that approach. Someone who has a reference to an arbitrary implementation of IDoSomeActionParameters and wants to capture the values therein has no way of knowing whether holding the reference will be sufficient, or if it must copy the values to some other object. Readable interfaces are useful in some contexts, but not as a means of making things immutable.
    – supercat
    Commented Sep 25, 2012 at 22:24
  • "IDoSomeActionParameters parameters" could be cast to DoSomeActionParameters and changed. The developer may not even realise that they are circumventing an attempt to make parameters imutable Commented Apr 6, 2016 at 14:55
6

How about creating a builder class inside your data class. The data class will have all the setters as private and only the builder will be able to set them.

public class DoSomeActionParameters
    {
        public string A { get; private set; }
        public string B  { get; private set; }
        public DateTime C { get; private set; }
        public OtherEnum D  { get; private set; }
        public string E  { get; private set; }
        public string F  { get; private set; }

        public class Builder
        {
            DoSomeActionParameters obj = new DoSomeActionParameters();

            public string A
            {
                set { obj.A = value; }
            }
            public string B
            {
                set { obj.B = value; }
            }
            public DateTime C
            {
                set { obj.C = value; }
            }
            public OtherEnum D
            {
                set { obj.D = value; }
            }
            public string E
            {
                set { obj.E = value; }
            }
            public string F
            {
                set { obj.F = value; }
            }

            public DoSomeActionParameters Build()
            {
                return obj;
            }
        }
    }

    public class Example
    {

        private void DoSth()
        {
            var data = new DoSomeActionParameters.Builder()
            {
                A = "",
                B = "",
                C = DateTime.Now,
                D = testc,
                E = "",
                F = ""
            }.Build();
        }
    }
5
  • 1
    +1 That is a perfectly valid solution but I think it's too much scaffolding to maintain such a simple design decision. Especially when the "readonly struct" solution is "very" close to ideal. Commented Jun 4, 2011 at 22:42
  • 2
    How does this solve the "too many parameters" problem? The syntax might be different, but the problem looks the same. This is not a criticism, I'm just curious because I am not familiar with this pattern.
    – alexD
    Commented Jun 5, 2011 at 2:17
  • 1
    @alexD this solves the problem with having too many function parameters and keeping the object immutable. Only the builder class can set the private properties and once you get the parameters object you can't change it. The problem is it requires a lot of scaffolding code.
    – marto
    Commented Jun 5, 2011 at 7:19
  • 5
    Parameter object in your solution is not immutable. Someone who saves the builder can edit parameters even after building
    – astef
    Commented Sep 12, 2014 at 15:18
  • 2
    To @astef's point, as it's currently written a DoSomeActionParameters.Builder instance can be used to create and configure exactly one DoSomeActionParameters instance. After calling Build() subsequent changes to the Builder's properties will continue modifying the original DoSomeActionParameters instance's properties, and subsequent calls to Build() will continue to return the same DoSomeActionParameters instance. It should really be public DoSomeActionParameters Build() { var oldObj = obj; obj = new DoSomeActionParameters(); return oldObj; }. Commented Jul 17, 2017 at 4:49
3

I know this is an old question but I thought I'd wade in with my suggestion as I've just had to solve the same problem. Now, admittadly my problem was slightly different to yours as I had the additional requirement of not wanting users to be able to construct this object themselves (all hydration of the data came from the database, so I could jail off all construction internally). This allowed me to use a private constructor and the following pattern;

    public class ExampleClass
    {
        //create properties like this...
        private readonly int _exampleProperty;
        public int ExampleProperty { get { return _exampleProperty; } }

        //Private constructor, prohibiting construction outside of this class
        private ExampleClass(ExampleClassParams parameters)
        {                
            _exampleProperty = parameters.ExampleProperty;
            //and so on... 
        }

        //The object returned from here will be immutable
        public ExampleClass GetFromDatabase(DBConnection conn, int id)
        {
            //do database stuff here (ommitted from example)
            ExampleClassParams parameters = new ExampleClassParams()
            {
                ExampleProperty = 1,
                ExampleProperty2 = 2
            };

            //Danger here as parameters object is mutable

            return new ExampleClass(parameters);    

            //Danger is now over ;)
        }

        //Private struct representing the parameters, nested within class that uses it.
        //This is mutable, but the fact that it is private means that all potential 
        //"damage" is limited to this class only.
        private struct ExampleClassParams
        {
            public int ExampleProperty { get; set; }
            public int AnotherExampleProperty { get; set; }
            public int ExampleProperty2 { get; set; }
            public int AnotherExampleProperty2 { get; set; }
            public int ExampleProperty3 { get; set; }
            public int AnotherExampleProperty3 { get; set; }
            public int ExampleProperty4 { get; set; }
            public int AnotherExampleProperty4 { get; set; } 
        }
    }
2

You could use a Builder-style approach, though depending on the complexity of your DoSomeAction method, this might be a touch heavyweight. Something along these lines:

public class DoSomeActionParametersBuilder
{
    public string A { get; set; }
    public string B { get; set; }
    public DateTime C { get; set; }
    public OtherEnum D { get; set; }
    public string E { get; set; }
    public string F { get; set; }

    public DoSomeActionParameters Build()
    {
        return new DoSomeActionParameters(A, B, C, D, E, F);
    }
}

public class DoSomeActionParameters
{
    public string A { get; private set; }
    public string B { get; private set; }
    public DateTime C { get; private set; }
    public OtherEnum D { get; private set; }
    public string E { get; private set; }
    public string F { get; private set; }

    public DoSomeActionParameters(string a, string b, DateTime c, OtherEnum d, string e, string f)
    {
        A = a;
        // etc.
    }
}

// usage
var actionParams = new DoSomeActionParametersBuilder
{
    A = "value for A",
    C = DateTime.Now,
    F = "I don't care for B, D and E"
}.Build();

result = foo.DoSomeAction(actionParams, out code);
1
  • 1
    Ah, marto beat me to the builder suggestion! Commented Jun 4, 2011 at 21:40
2

In addition to manji response - you may also want to split one operation into several smaller ones. Compare:

 BOOL WINAPI CreateProcess(
   __in_opt     LPCTSTR lpApplicationName,
   __inout_opt  LPTSTR lpCommandLine,
   __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
   __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
   __in         BOOL bInheritHandles,
   __in         DWORD dwCreationFlags,
   __in_opt     LPVOID lpEnvironment,
   __in_opt     LPCTSTR lpCurrentDirectory,
   __in         LPSTARTUPINFO lpStartupInfo,
   __out        LPPROCESS_INFORMATION lpProcessInformation
 );

and

 pid_t fork()
 int execvpe(const char *file, char *const argv[], char *const envp[])
 ...

For those who don't know POSIX the creation of child can be as easy as:

pid_t child = fork();
if (child == 0) {
    execl("/bin/echo", "Hello world from child", NULL);
} else if (child != 0) {
    handle_error();
}

Each design choice represent trade-off over what operations it may do.

PS. Yes - it is similar to builder - only in reverse (i.e. on callee side instead of caller). It may or may not be better then builder in this specific case.

2
  • It is a small operation but that's a good recommendation for anyone who is violating single-responsibility principle. My question takes place just after all other design improvements have been done. Commented Jun 5, 2011 at 10:20
  • Ups. Sorry - I ready a question before your edit and posted it later - hence I hadn't notice it. Commented Jun 5, 2011 at 11:37
2

here is a slightly different one from Mikeys but what I am trying to do is make the whole thing as little to write as possible

public class DoSomeActionParameters
{
    readonly string _a;
    readonly int _b;

    public string A { get { return _a; } }

    public int B{ get { return _b; } }

    DoSomeActionParameters(Initializer data)
    {
        _a = data.A;
        _b = data.B;
    }

    public class Initializer
    {
        public Initializer()
        {
            A = "(unknown)";
            B = 88;
        }

        public string A { get; set; }
        public int B { get; set; }

        public DoSomeActionParameters Create()
        {
            return new DoSomeActionParameters(this);
        }
    }
}

The DoSomeActionParameters is immutable as it can be and cannot be created directly as its default constructor is private

The initializer is not immutable, but only a transport

The usage takes advantage of the initializer on the Initializer (if you get my drift) And I can have defaults in the Initializer default constructor

DoSomeAction(new DoSomeActionParameters.Initializer
            {
                A = "Hello",
                B = 42
            }
            .Create());

The parameters will be optional here, if you want some to be required you could put them in the Initializer default constructor

And validation could go in the Create method

public class Initializer
{
    public Initializer(int b)
    {
        A = "(unknown)";
        B = b;
    }

    public string A { get; set; }
    public int B { get; private set; }

    public DoSomeActionParameters Create()
    {
        if (B < 50) throw new ArgumentOutOfRangeException("B");

        return new DoSomeActionParameters(this);
    }
}

So now it looks like

DoSomeAction(new DoSomeActionParameters.Initializer
            (b: 42)
            {
                A = "Hello"
            }
            .Create());

Still a little kooki I know, but going to try it anyway

Edit: moving the create method to a static in the parameters object and adding a delegate which passes the initializer takes some of the kookieness out of the call

public class DoSomeActionParameters
{
    readonly string _a;
    readonly int _b;

    public string A { get { return _a; } }
    public int B{ get { return _b; } }

    DoSomeActionParameters(Initializer data)
    {
        _a = data.A;
        _b = data.B;
    }

    public class Initializer
    {
        public Initializer()
        {
            A = "(unknown)";
            B = 88;
        }

        public string A { get; set; }
        public int B { get; set; }
    }

    public static DoSomeActionParameters Create(Action<Initializer> assign)
    {
        var i = new Initializer();
        assign(i)

        return new DoSomeActionParameters(i);
    }
}

So the call now looks like this

DoSomeAction(
        DoSomeActionParameters.Create(
            i => {
                i.A = "Hello";
            })
        );
1

Use the structure, but instead of public fields, have public properties:

•Everybody (including FXCop & Jon Skeet) agree that exposing public fields are bad.

Jon and FXCop will be satisified because you are exposing properites not fields.

•Eric Lippert et al say relying on readonly fields for immutability is a lie.

Eric will be satisifed because using properties, you can ensure that the value is only set once.

    private bool propC_set=false;
    private date pC;
    public date C {
        get{
            return pC;
        }
        set{
            if (!propC_set) {
               pC = value;
            }
            propC_set = true;
        }
    }

One semi-immutable object (value can be set but not changed). Works for value and Reference types.

2
  • +1 Maybe private readonly fields and public getter-only properties could be combined in a struct to allow a less verbose solution. Commented Jun 5, 2011 at 10:25
  • Public read-write properties on structures that mutate this are far more evil than public fields. I'm not sure why you think only setting the value once makes things "okay"; if one starts with a default instance of a struct, the problems associated with this-mutating properties will still exist.
    – supercat
    Commented Sep 25, 2012 at 22:27
0

A variant of Samuel's answer that I used in my project when I had the same problem:

class MagicPerformer
{
    public int Param1 { get; set; }
    public string Param2 { get; set; }
    public DateTime Param3 { get; set; }

    public MagicPerformer SetParam1(int value) { this.Param1 = value; return this; }
    public MagicPerformer SetParam2(string value) { this.Param2 = value; return this; }
    public MagicPerformer SetParam4(DateTime value) { this.Param3 = value; return this; }

    public void DoMagic() // Uses all the parameters and does the magic
    {
    }
}

And to use:

new MagicPerformer().SeParam1(10).SetParam2("Yo!").DoMagic();

In my case the parameters were intentionally modifiable, because the setter methods didn't allow for all possible combinations, and just exposed common combinations of them. That's because some of my parameters were pretty complex and writing methods for all possible cases would have been difficult and unnecessary (crazy combinations are rarely used).

2
  • This is a mutable class regardless. Commented Jun 6, 2011 at 8:09
  • @ssg - Well, yes, it is. The DoMagic has in its contract though that it will not modify the object. But I guess it doesn't protect from accidental modifications.
    – Vilx-
    Commented Jun 6, 2011 at 11:12

Not the answer you're looking for? Browse other questions tagged or ask your own question.