2009-11-01 74 views
37

我怎样才能(如果有可能的话)在C#for循环中初始化多个不同类型的变量?例如:在C#中进行多个初始化'for'循环

for (MyClass i = 0, int j = 1; j<3; j++,i++) 
+1

MyClass是如何定义的? – Dani 2009-11-01 22:21:21

+2

你为什么要这么做。这将很难阅读和理解,因此EVIL [tm]的定义。 – EricSchaefer 2009-11-01 22:23:49

+1

Dani:MyClass基本上是一个整数,带有定义的最大值,用于索引表示一个圆圈的数组。EricSchaefer:为该循环设置一个独立的迭代计数器(另一个来自外部)。 for循环将包含像array [i] = j * step; - 在这种情况下,我不担心redabilty。 – Lukas 2009-11-01 23:07:05

回答

60

不能这样做。把声明的一个循环之前:

MyClass i = 0; 
for (int j = 1; j < 3; j++, i++) 

或为对称性,他们两个:

MyClass i = 0; 
int j = 1; 
for (; j < 3; j++, i++) 

这也有可能是变量的一个比另一个更主要。在这种情况下,它可能是整洁有一个是循环变量,并与其他seperately处理,像这样:

MyClass i = 0; 
for (int j = 0; j < 3; j++) 
{ 
    ... 
    i++; 
} 

注意,如果ij是同一类型的,那么你就可以宣布他们两个在for循环中:

for (int i = 0, j = 1; j < 3; j++, i++) 
0

我不认为你可以在for循环中定义多个类型。 只适用于(int i = 0,j = 3; j < 7; j ++,i ++)

8

是的,可以这样做。您可以在for语句中初始化不同类型的变量,但不能在for语句中声明不同类型的变量。为了在for语句中初始化不同类型的变量,你必须在之前声明for循环之前的所有类型。例如:

int xx; 
string yy; 
for(xx=0, yy=""; xx<10; xx++) 
    { 
    .... 
    } 

[编辑]添加更多信息的完整性。这超出了OP所要求的范围,但可能对其他人有所帮助。 在for循环中初始化相同类型的变量非常简单,只需用逗号分隔初始化即可。您也可以在第三部分中更改多个变量。在第二个比较部分中,您不能有多个逗号分隔的部分,但您可以使用& & ||和!基于多个变量制作复杂的布尔部分。

for(int i=0, j=0, k=99; i<10 && k<200; i++, j++, k += 2) 

然而,这是不是一个好的做法,以使该是如此复杂,这是很难理解到底是怎么回事声明。

0

您不能在循环结构中定义多个然后一个变量。请尝试下面的代码:

选项1:一个变量在循环之前声明并在循环中手动递增,每次迭代一次。

MyClass i = 0; 
for (int j = 1; j<3; j++) 
{ 
    //do stuff 
    i++ 
} 

选项2:两个变量的for循环和一个在环结构递增,并且在其他环手动设置之前。

MyClass i = 0; 
int j = 1 
for (; j<3; j++) 
{ 
    //do stuff 
    i++ 
} 

方案3:两个变量的循环结构之前设置,并且两个变量在循环增加,使循环只检查一个条件,这在这一点上,你可能只是做一会循环。

MyClass i = 0; 
int j = 1 
for (; j<3) 
{ 
    //do stuff 
    j++ 
    i++ 
} 

选项4:写入作为while循环

MyClass i = 0; 
int j = 1 
while (j<3) 
{ 
    //do stuff 
    j++ 
    i++ 
} 
1
for (initializer; condition; iterator) 
{ 
body 
} 

初始化部设定的初始条件。在进入循环之前,本节中的语句只运行一次。该部分只能包含以下两个选项之一。

1)本地循环变量的声明和初始化。该变量对于循环而言是本地的,并且不能从循环外部访问。

2)以下列表中的零个或多个语句表达式,用逗号分隔。

assignment statement 

    invocation of a method 

    prefix or postfix increment expression, such as ++i or i++ 

    prefix or postfix decrement expression, such as --i or i-- 

    creation of an object by using new 

    await expression 

正如我们所知道的,编译器并不是用来接受我们期望的方式。因此,在编写for循环内的初始化程序段之前,必须遵循以上规则。

http://msdn.microsoft.com/en-us/library/ch45axte.aspx

7

是否有害?

是的,非常非常。语言解析器有两个重要的职责。一个是大家熟悉的工作,将文本转换为可执行程序。但非常重要,它可以检测到无效的程序,并为程序员生成一个有意义的诊断信息,以便他可以修复他的代码。

在非常基础的层面,语言分析器声明陈述表达区分。花括号语言会混淆这种区别,您可以将任何表达式转换为语句,只需在其后面放一个分号即可。在某些情况下,在声明中接受声明,for(;;)语句就是一个很好的例子。大多数说白了,这个语法是在C或C++语言完全可以接受的:

int x = 42; 
x; 

这不完全是好事,这是无稽之谈代码。 C#语言提高了这个标准,它会拒绝这个。但不是:

int x = 42; 
x++; 

添加到语言分析器的特殊规则来接受此规则。

没有任何花括号语言会接受将声明转换为表达式。这种方式是疯狂的,龙在地图的尽头,船掉下来没有留下好消息报告。逗号操作符需要左手和右手操作数为表达式。宣言不是一个表达,故事结束。

0

这是不是特别我的专长,但这里是我的话题头脑风暴:

在programmimng语言理论,语言的语法必须毫不含糊地界定。自从我研究这些主题已经有几年了,我无法深入研究它的细节。但是你可以检查Backus-Naur Form这是一种表示技术来描述语言的“语法”。这是我唯一熟悉的。

因此,在解析代码时使用此描述。你的解析器必须能够将你的代码的每一部分与语法的“规则”联系起来。你可以看到C#语法here。它有些类似的形式。

(1)for语句的语法看看

for-statement: 
    for(for-initializer;for-condition;for-iterator) 
     embedded-statement 

,然后初始化程序语法

for-initializer: 
    local-variable-declaration 
    statement-expression-list 

注意语句表达列表仅用于在for循环。它也是逗号分隔的语句表达式列表。

我会在这里留下一些中间步骤,但您可以按照语法让自己更适应这个想法。

Here是一个很好的基本幻灯片集,演示了如何使用简单简单的语法即可获得复杂的事情。 (2)我们在1中观察到的是我们可以为for循环的初始化部分添加什么东西。我们知道你的建议为什么不起作用。作为赏金猎人,让我们来分析一下这个设计选择的原因。

首先,这是一个设计选择。您可以设计或找到允许的语言。通过改变语法应该是可能的,但是一些语法上的改变可能是必要的。这是为什么;

如果你打算放置多个声明语句,你可能想要类似声明列表。你打算使用分离器,你可能不想使用;因为使用分号分隔for循环的部分。因此,您可以随时使用逗号,但如果使用逗号,则声明列表规则只能用于for循环,因为在代码中使用逗号分隔的声明会引起混淆。

二,有什么问题呢?如果你问我,我也没有看到任何错误。如果他们设计了它应该工作的语言。 (我不是说我刚才的小品是100%正确的,它只能作为一个头脑风暴会议的出发点。)

那么,为什么他们不选择?是什么促使他们避免这种情况?

  • 通过将该规则添加到您的 语法中,您引入了多少复杂因素?
  • 你还要考虑你有多少额外的规则添加 使语言歧义?
  • 您是否意识到已经存在的规则有多复杂?
  • 为解析器和编译器增加了多少工作量?

毕竟这些和许多其他方面的考虑,

  • 多少钱添加到您的语言的实用性,可读性?
  • 或者你甚至会失去一些可读性?
  • 您是否考虑过,程序员需要这些类型的 循环的频率如何?
  • 即使他们经常需要它,你应该鼓励或者 不鼓励他们进行这种类型的编码?

...还有很多像这样的问题,一定要小心。通过查看这些问题及其分析,我认为编译器设计人员的设计选择几乎是最可接受的方法。

24

当然可以做到。只需使用动态关键字:

public static void Main(string[] args) { 
    for (dynamic x = 0, y = new MyClass { a = 20, b = 30 }; x < 100; x++, y.a++, y.b--) { 
     Console.Write("X=" + x + " (" + x.GetType() + "\n" + 
         "Y.a=" + y.a + ",Y.b=" + y.b + " (" + y.GetType() + "\n"); 
    } 
} 

class MyClass { 
    public int a = 0, b = 0; 
} 

有一个伟大的一天!

+9

史诗,但我会建议不要使用:) – CodeMonkey 2015-05-05 12:07:55

+0

不要这样做,除非你想调试运行时异常,因为静态类型检查器不会再警告你,如果你使用'MyClass'的不存在成员或使用'x像'串'一样。如果您担心范围内的变量太多,请按照@Vladimir Liubimov的建议(在他的回答中)(http://stackoverflow.com/a/36053107/345004),并将其嵌套在一个块中。 – enzi 2016-08-24 08:21:29

0

没有理由不需要在带内初始化替代索引器。它保持环境清晰无用的var分配。

for (int x=0,y = 0; x < 100; x++) 
{ 
    if (true) { y++; } 
    // ... use y as a conditional indexer 
    // ... x is always the loop indexer 
    // ... no overflows 
} 
4

我usualy把声明循环之前,并使用额外的大括号限制的声明范围:

{ //limit the scope: i, count, iDivisibleBy2, iDivisibleBy3, iDivisibleBy5 
    int i = 0, count = 100; 
    bool iDivisibleBy2 = true, iDivisibleBy3 = true, iDivisibleBy5 = true; 
    for(; i < count; ++i, iDivisibleBy2 = (i % 2 == 0), iDivisibleBy3 = (i % 3 == 0), iDivisibleBy5 = (i % 5 == 0)) 
    { 
     //... 
    } 
} 
0

让我们有一些乐趣。我将留给你决定是否应该在任何地方实际使用...:P

可以(间接)声明和初始化许多变量,以便在for循环初始化程序中使用不同的类型而不使用动态关键字。只需为您的索引变量使用自定义结构。

for(var i = new I1<MyClass>(0, 1); i < 3; i++, i.a++) { 
    MyClass myClass = i.a; 
} 

重载运营商意味着你可以使用“我”喜欢到处一个int。对于一个干净的语法,初始化0:

for(I1<float> i = 0; i < array.Length; i++) { 
    i.a += array[i]; // accumulate a float value 
} 

一些更傻的例子:

// Three variables 
for(I3<object, string, int> i = 0; i < 100; i++) { 
    i.a = new object(); 
    i.b = "This is index " + i; 
    i.c = 100 - i; 
} 

// A class 
for(var i = new I1<SomeClass>(0, new SomeClass()); i < 20; i += 2) { 
    i.a.someVar1 = "We can have even more variables in here! Woot!"; 
    i.a.DoSomething(i); 
} 

// An array 
for(var i = new I1<string[]>(0, new[] { "Hi", "Mom" }); i < 10; i++) { 
    for(int j = 0; j < i.a.Length; j++) { 
     Log(i.a[j]); 
    } 
} 

这里有结构。他们工作但没有经过彻底测试,因此可能存在一些错误:

public struct I1<T> { 

    public int index; 
    public T a; 

    public I1(int index) { 
     this.index = index; 
     this.a = default(T); 
    } 
    public I1(int index, T a) { 
     this.index = index; 
     this.a = a; 
    } 

    public override bool Equals(object obj) { 
     if(!(obj is I1<T>)) return false; 
     I1<T> other = (I1<T>)obj; 
     return index == other.index && EqualityComparer<T>.Default.Equals(a, other.a); 
    } 

    public override int GetHashCode() { 
     int hash = 17; 
     hash = hash * 29 + index.GetHashCode(); 
     if(typeof(T).IsValueType && !object.ReferenceEquals(a, null)) hash = hash * 29 + a.GetHashCode(); 
     return hash; 
    } 

    public override string ToString() { 
     return index.ToString(); 
    } 

    public static implicit operator I1<T>(int other) { 
     return new I1<T>(other); 
    } 

    public static implicit operator int(I1<T> other) { 
     return other.index; 
    } 

    // Unary operators 

    public static int operator +(I1<T> a) { 
     return +a.index; 
    } 

    public static int operator -(I1<T> a) { 
     return -a.index; 
    } 

    public static int operator ~(I1<T> a) { 
     return ~a.index; 
    } 

    public static I1<T> operator ++(I1<T> a) { 
     a.index++; 
     return a; 
    } 

    public static I1<T> operator --(I1<T> a) { 
     a.index--; 
     return a; 
    } 

    // Binary operators 

    public static I1<T> operator +(I1<T> a, int b) { 
     a.index += b; 
     return a; 
    } 
    public static I1<T> operator +(int a, I1<T> b) { 
     b.index += a; 
     return b; 
    } 

    public static I1<T> operator -(I1<T> a, int b) { 
     a.index -= b; 
     return a; 
    } 
    public static I1<T> operator -(int a, I1<T> b) { 
     b.index = a - b.index; 
     return b; 
    } 

    public static I1<T> operator *(I1<T> a, int b) { 
     a.index *= b; 
     return a; 
    } 
    public static I1<T> operator *(int a, I1<T> b) { 
     b.index *= a; 
     return b; 
    } 

    public static I1<T> operator /(I1<T> a, int b) { 
     a.index /= b; 
     return a; 
    } 
    public static I1<T> operator /(int a, I1<T> b) { 
     b.index = a/b.index; 
     return b; 
    } 

    public static I1<T> operator %(I1<T> a, int b) { 
     a.index %= b; 
     return a; 
    } 
    public static I1<T> operator %(int a, I1<T> b) { 
     b.index = a % b.index; 
     return b; 
    } 

    public static I1<T> operator &(I1<T> a, int b) { 
     a.index &= b; 
     return a; 
    } 
    public static I1<T> operator &(int a, I1<T> b) { 
     b.index = a & b.index; 
     return b; 
    } 

    public static I1<T> operator |(I1<T> a, int b) { 
     a.index |= b; 
     return a; 
    } 
    public static I1<T> operator |(int a, I1<T> b) { 
     b.index = a | b.index; 
     return b; 
    } 

    public static I1<T> operator ^(I1<T> a, int b) { 
     a.index ^= b; 
     return a; 
    } 
    public static I1<T> operator ^(int a, I1<T> b) { 
     b.index = a^b.index; 
     return b; 
    } 

    public static I1<T> operator <<(I1<T> a, int b) { 
     a.index <<= b; 
     return a; 
    } 

    public static I1<T> operator >>(I1<T> a, int b) { 
     a.index >>= b; 
     return a; 
    } 

    // Comparison operators 

    public static bool operator ==(I1<T> a, int b) { 
     return a.index == b; 
    } 
    public static bool operator ==(int a, I1<T> b) { 
     return a == b.index; 
    } 

    public static bool operator !=(I1<T> a, int b) { 
     return a.index != b; 
    } 
    public static bool operator !=(int a, I1<T> b) { 
     return a != b.index; 
    } 

    public static bool operator <(I1<T> a, int b) { 
     return a.index < b; 
    } 
    public static bool operator <(int a, I1<T> b) { 
     return a < b.index; 
    } 

    public static bool operator >(I1<T> a, int b) { 
     return a.index > b; 
    } 
    public static bool operator >(int a, I1<T> b) { 
     return a > b.index; 
    } 

    public static bool operator <=(I1<T> a, int b) { 
     return a.index <= b; 
    } 
    public static bool operator <=(int a, I1<T> b) { 
     return a <= b.index; 
    } 

    public static bool operator >=(I1<T> a, int b) { 
     return a.index >= b; 
    } 
    public static bool operator >=(int a, I1<T> b) { 
     return a >= b.index; 
    } 
} 

public struct I2<T1, T2> { 

    public int index; 
    public T1 a; 
    public T2 b; 

    public I2(int index) { 
     this.index = index; 
     this.a = default(T1); 
     this.b = default(T2); 
    } 
    public I2(int index, T1 a) { 
     this.index = index; 
     this.a = a; 
     this.b = default(T2); 
    } 
    public I2(int index, T1 a, T2 b) { 
     this.index = index; 
     this.a = a; 
     this.b = b; 
    } 

    public override bool Equals(object obj) { 
     if(!(obj is I2<T1, T2>)) return false; 
     I2<T1, T2> other = (I2<T1, T2>)obj; 
     return index == other.index && EqualityComparer<T1>.Default.Equals(a, other.a) && EqualityComparer<T2>.Default.Equals(b, other.b); 
    } 

    public override int GetHashCode() { 
     int hash = 17; 
     hash = hash * 29 + index.GetHashCode(); 
     if(typeof(T1).IsValueType && !object.ReferenceEquals(a, null)) hash = hash * 29 + a.GetHashCode(); 
     if(typeof(T2).IsValueType && !object.ReferenceEquals(b, null)) hash = hash * 29 + b.GetHashCode(); 
     return hash; 
    } 

    public override string ToString() { 
     return index.ToString(); 
    } 

    public static implicit operator I2<T1, T2>(int other) { 
     return new I2<T1, T2>(other); 
    } 

    public static implicit operator int(I2<T1, T2> other) { 
     return other.index; 
    } 

    // Unary operators 

    public static int operator +(I2<T1, T2> a) { 
     return +a.index; 
    } 

    public static int operator -(I2<T1, T2> a) { 
     return -a.index; 
    } 

    public static int operator ~(I2<T1, T2> a) { 
     return ~a.index; 
    } 

    public static I2<T1, T2> operator ++(I2<T1, T2> a) { 
     a.index++; 
     return a; 
    } 

    public static I2<T1, T2> operator --(I2<T1, T2> a) { 
     a.index--; 
     return a; 
    } 

    // Binary operators 

    public static I2<T1, T2> operator +(I2<T1, T2> a, int b) { 
     a.index += b; 
     return a; 
    } 
    public static I2<T1, T2> operator +(int a, I2<T1, T2> b) { 
     b.index += a; 
     return b; 
    } 

    public static I2<T1, T2> operator -(I2<T1, T2> a, int b) { 
     a.index -= b; 
     return a; 
    } 
    public static I2<T1, T2> operator -(int a, I2<T1, T2> b) { 
     b.index = a - b.index; 
     return b; 
    } 

    public static I2<T1, T2> operator *(I2<T1, T2> a, int b) { 
     a.index *= b; 
     return a; 
    } 
    public static I2<T1, T2> operator *(int a, I2<T1, T2> b) { 
     b.index *= a; 
     return b; 
    } 

    public static I2<T1, T2> operator /(I2<T1, T2> a, int b) { 
     a.index /= b; 
     return a; 
    } 
    public static I2<T1, T2> operator /(int a, I2<T1, T2> b) { 
     b.index = a/b.index; 
     return b; 
    } 

    public static I2<T1, T2> operator %(I2<T1, T2> a, int b) { 
     a.index %= b; 
     return a; 
    } 
    public static I2<T1, T2> operator %(int a, I2<T1, T2> b) { 
     b.index = a % b.index; 
     return b; 
    } 

    public static I2<T1, T2> operator &(I2<T1, T2> a, int b) { 
     a.index &= b; 
     return a; 
    } 
    public static I2<T1, T2> operator &(int a, I2<T1, T2> b) { 
     b.index = a & b.index; 
     return b; 
    } 

    public static I2<T1, T2> operator |(I2<T1, T2> a, int b) { 
     a.index |= b; 
     return a; 
    } 
    public static I2<T1, T2> operator |(int a, I2<T1, T2> b) { 
     b.index = a | b.index; 
     return b; 
    } 

    public static I2<T1, T2> operator ^(I2<T1, T2> a, int b) { 
     a.index ^= b; 
     return a; 
    } 
    public static I2<T1, T2> operator ^(int a, I2<T1, T2> b) { 
     b.index = a^b.index; 
     return b; 
    } 

    public static I2<T1, T2> operator <<(I2<T1, T2> a, int b) { 
     a.index <<= b; 
     return a; 
    } 

    public static I2<T1, T2> operator >>(I2<T1, T2> a, int b) { 
     a.index >>= b; 
     return a; 
    } 

    // Comparison operators 

    public static bool operator ==(I2<T1, T2> a, int b) { 
     return a.index == b; 
    } 
    public static bool operator ==(int a, I2<T1, T2> b) { 
     return a == b.index; 
    } 

    public static bool operator !=(I2<T1, T2> a, int b) { 
     return a.index != b; 
    } 
    public static bool operator !=(int a, I2<T1, T2> b) { 
     return a != b.index; 
    } 

    public static bool operator <(I2<T1, T2> a, int b) { 
     return a.index < b; 
    } 
    public static bool operator <(int a, I2<T1, T2> b) { 
     return a < b.index; 
    } 

    public static bool operator >(I2<T1, T2> a, int b) { 
     return a.index > b; 
    } 
    public static bool operator >(int a, I2<T1, T2> b) { 
     return a > b.index; 
    } 

    public static bool operator <=(I2<T1, T2> a, int b) { 
     return a.index <= b; 
    } 
    public static bool operator <=(int a, I2<T1, T2> b) { 
     return a <= b.index; 
    } 

    public static bool operator >=(I2<T1, T2> a, int b) { 
     return a.index >= b; 
    } 
    public static bool operator >=(int a, I2<T1, T2> b) { 
     return a >= b.index; 
    } 
} 

public struct I3<T1, T2, T3> { 

    public int index; 
    public T1 a; 
    public T2 b; 
    public T3 c; 

    public I3(int index) { 
     this.index = index; 
     this.a = default(T1); 
     this.b = default(T2); 
     this.c = default(T3); 
    } 
    public I3(int index, T1 a) { 
     this.index = index; 
     this.a = a; 
     this.b = default(T2); 
     this.c = default(T3); 
    } 
    public I3(int index, T1 a, T2 b) { 
     this.index = index; 
     this.a = a; 
     this.b = b; 
     this.c = default(T3); 
    } 
    public I3(int index, T1 a, T2 b, T3 c) { 
     this.index = index; 
     this.a = a; 
     this.b = b; 
     this.c = c; 
    } 

    public override bool Equals(object obj) { 
     if(!(obj is I3<T1, T2, T3>)) return false; 
     I3<T1, T2, T3> other = (I3<T1, T2, T3>)obj; 
     return index == other.index && EqualityComparer<T1>.Default.Equals(a, other.a) && 
      EqualityComparer<T2>.Default.Equals(b, other.b) && 
      EqualityComparer<T3>.Default.Equals(c, other.c); 
    } 

    public override int GetHashCode() { 
     int hash = 17; 
     hash = hash * 29 + index.GetHashCode(); 
     if(typeof(T1).IsValueType && !object.ReferenceEquals(a, null)) hash = hash * 29 + a.GetHashCode(); 
     if(typeof(T2).IsValueType && !object.ReferenceEquals(b, null)) hash = hash * 29 + b.GetHashCode(); 
     if(typeof(T3).IsValueType && !object.ReferenceEquals(c, null)) hash = hash * 29 + c.GetHashCode(); 
     return hash; 
    } 

    public override string ToString() { 
     return index.ToString(); 
    } 

    public static implicit operator I3<T1, T2, T3>(int other) { 
     return new I3<T1, T2, T3>(other); 
    } 

    public static implicit operator int(I3<T1, T2, T3> other) { 
     return other.index; 
    } 

    // Unary operators 

    public static int operator +(I3<T1, T2, T3> a) { 
     return +a.index; 
    } 

    public static int operator -(I3<T1, T2, T3> a) { 
     return -a.index; 
    } 

    public static int operator ~(I3<T1, T2, T3> a) { 
     return ~a.index; 
    } 

    public static I3<T1, T2, T3> operator ++(I3<T1, T2, T3> a) { 
     a.index++; 
     return a; 
    } 

    public static I3<T1, T2, T3> operator --(I3<T1, T2, T3> a) { 
     a.index--; 
     return a; 
    } 

    // Binary operators 

    public static I3<T1, T2, T3> operator +(I3<T1, T2, T3> a, int b) { 
     a.index += b; 
     return a; 
    } 
    public static I3<T1, T2, T3> operator +(int a, I3<T1, T2, T3> b) { 
     b.index += a; 
     return b; 
    } 

    public static I3<T1, T2, T3> operator -(I3<T1, T2, T3> a, int b) { 
     a.index -= b; 
     return a; 
    } 
    public static I3<T1, T2, T3> operator -(int a, I3<T1, T2, T3> b) { 
     b.index = a - b.index; 
     return b; 
    } 

    public static I3<T1, T2, T3> operator *(I3<T1, T2, T3> a, int b) { 
     a.index *= b; 
     return a; 
    } 
    public static I3<T1, T2, T3> operator *(int a, I3<T1, T2, T3> b) { 
     b.index *= a; 
     return b; 
    } 

    public static I3<T1, T2, T3> operator /(I3<T1, T2, T3> a, int b) { 
     a.index /= b; 
     return a; 
    } 
    public static I3<T1, T2, T3> operator /(int a, I3<T1, T2, T3> b) { 
     b.index = a/b.index; 
     return b; 
    } 

    public static I3<T1, T2, T3> operator %(I3<T1, T2, T3> a, int b) { 
     a.index %= b; 
     return a; 
    } 
    public static I3<T1, T2, T3> operator %(int a, I3<T1, T2, T3> b) { 
     b.index = a % b.index; 
     return b; 
    } 

    public static I3<T1, T2, T3> operator &(I3<T1, T2, T3> a, int b) { 
     a.index &= b; 
     return a; 
    } 
    public static I3<T1, T2, T3> operator &(int a, I3<T1, T2, T3> b) { 
     b.index = a & b.index; 
     return b; 
    } 

    public static I3<T1, T2, T3> operator |(I3<T1, T2, T3> a, int b) { 
     a.index |= b; 
     return a; 
    } 
    public static I3<T1, T2, T3> operator |(int a, I3<T1, T2, T3> b) { 
     b.index = a | b.index; 
     return b; 
    } 

    public static I3<T1, T2, T3> operator ^(I3<T1, T2, T3> a, int b) { 
     a.index ^= b; 
     return a; 
    } 
    public static I3<T1, T2, T3> operator ^(int a, I3<T1, T2, T3> b) { 
     b.index = a^b.index; 
     return b; 
    } 

    public static I3<T1, T2, T3> operator <<(I3<T1, T2, T3> a, int b) { 
     a.index <<= b; 
     return a; 
    } 

    public static I3<T1, T2, T3> operator >>(I3<T1, T2, T3> a, int b) { 
     a.index >>= b; 
     return a; 
    } 

    // Comparison operators 

    public static bool operator ==(I3<T1, T2, T3> a, int b) { 
     return a.index == b; 
    } 
    public static bool operator ==(int a, I3<T1, T2, T3> b) { 
     return a == b.index; 
    } 

    public static bool operator !=(I3<T1, T2, T3> a, int b) { 
     return a.index != b; 
    } 
    public static bool operator !=(int a, I3<T1, T2, T3> b) { 
     return a != b.index; 
    } 

    public static bool operator <(I3<T1, T2, T3> a, int b) { 
     return a.index < b; 
    } 
    public static bool operator <(int a, I3<T1, T2, T3> b) { 
     return a < b.index; 
    } 

    public static bool operator >(I3<T1, T2, T3> a, int b) { 
     return a.index > b; 
    } 
    public static bool operator >(int a, I3<T1, T2, T3> b) { 
     return a > b.index; 
    } 

    public static bool operator <=(I3<T1, T2, T3> a, int b) { 
     return a.index <= b; 
    } 
    public static bool operator <=(int a, I3<T1, T2, T3> b) { 
     return a <= b.index; 
    } 

    public static bool operator >=(I3<T1, T2, T3> a, int b) { 
     return a.index >= b; 
    } 
    public static bool operator >=(int a, I3<T1, T2, T3> b) { 
     return a >= b.index; 
    } 
}