1

I would like to create a method that uses the keyword in instead of a comma to separate parameters in a method declaration; something similar to the foreach(a in b) method.

Example

Class Structure

public class Length
{
    public double Inches;
    public double Feet;
    public double Yards;

    public enum Unit { Inch, Foot, Yard }

    Dictionary<Unit, double> inchFactor = new Dictionary<Unit, double>()
    {
        { Unit.Inch, 1 },
        { Unit.Foot, 12 },
        { Unit.Yard, 36 }
    };

    public Length(double value, Unit unit)
    {
        this.Inches = value * inchFactor[unit];
        this.Feet = this.Inches / inchFactor[Unit.Foot];
        this.Yards = this.Inches / inchFactor[Unit.Yard];
    }
}

Method Definition in Class

// I'd like to know how to use "in" like this  ↓
public List<Length> MultiplesOf(Length divisor in Length dividend)
{
    double inchEnumeration = divisor.Inches;
    List<Length> multiples = new List<Length>();

    while (inchEnumeration <= dividend.Inches)
    {
        multiples.Add(new Length(inchEnumeration, Length.Unit.Inch));
        inchEnumeration += divisor.Inches;
    }

    return multiples;
}

Ideal Implementation

private void DrawRuler()
{
    Length eighthInch = new Length(0.125, Length.Unit.Inch);
    Length oneFoot = new Length(1, Length.Unit.Foot);

    // Awesome.
    List<Length> tickGroup = Length.MultiplesOf(eighthInch in oneFoot);

    double inchPixels = 10;
    foreach (Length tick in tickGroup)
    {
        // Draw ruler.
    }
}

I've looked into creating new keywords, but it looks like C# does not support defining keywords.

Tyler Pantuso
  • 835
  • 8
  • 16
  • 1
    You can't. That syntax in not valid C# syntax. `foreach(a in b)` is valid syntax for that keyword and is not usable by other methods. – D Stanley Jan 15 '16 at 22:28
  • 2
    "*it looks like C# does not support defining keywords*" Correct. – Jeroen Vannevel Jan 15 '16 at 22:28
  • @DStanley : I thought it may be possible when I looked at a source code file for the foreach loop. It looks like regular C#. Do we not have access to the same resources as the `System` and other namespaces did with their method declarations? – Tyler Pantuso Jan 15 '16 at 22:36
  • @Micky : I did. It won't even compile. `) expected` – Tyler Pantuso Jan 15 '16 at 22:37
  • @TylerPantuso: Which language are you familiar with that supports defining keywords? Custom keywords are not supported by any C-derived language AFAIK. – Douglas Jan 15 '16 at 22:41
  • @Douglas : I am only familiar with the basics of C#. – Tyler Pantuso Jan 15 '16 at 22:42
  • @TylerPantuso "a source code file for the foreach loop" `foreach` does not have "source code". it is a compiler mechanism that converts the loop into a call to `IEnumerable` methods, so I'm not sure what you're looking at. – D Stanley Jan 16 '16 at 03:14

2 Answers2

2

As has been mentioned in the comments, you cannot define custom keywords in C# (unless you extend the compiler, which is an advanced task). However, if your goal is to clarify the meaning of the two arguments, then I would suggest using named arguments instead:

// Define the method as usual:
public List<Length> MultiplesOf(Length divisor, Length dividend)
{
    // ...
}

// Then call it like so, explicitly showing what is the divisor and the dividend:  
List<Length> tickGroup = Length.MultiplesOf(divisor: eighthInch, dividend: oneFoot);
Douglas
  • 53,759
  • 13
  • 140
  • 188
1

While you can't redefine an existing keyword, there is other way to accomplish what you in a slightly different way using Fluent Interface :

public class Length
{
    // ...

    public static IFluentSyntaxProvider MultiplesOf(Length divisor)
    {
        return new FluentSyntaxProvider(divisor);
    }

    public interface IFluentSyntaxProvider
    {
        List<Length> In(Length dividend);
    }
    private class FluentSyntaxProvider : IFluentSyntaxProvider
    {
        private Length divisor;

        public FluentSyntaxProvider(Length divisor)
        {
            this.divisor = divisor;
        }

        public List<Length> In(Length dividend)
        {
            double inchEnumeration = divisor.Inches;
            List<Length> multiples = new List<Length>();

            while (inchEnumeration <= dividend.Inches)
            {
                multiples.Add(new Length(inchEnumeration, Length.Unit.Inch));
                inchEnumeration += divisor.Inches;
            }

            return multiples;
        }
    }
}

Example of usage :

// Awesome.
List<Length> tickGroup = Length.MultiplesOf(eighthInch).In(oneFoot);
Xiaoy312
  • 14,292
  • 1
  • 32
  • 44