A: 95 bytes
class A{public static int i=2;static void Main(string[]args){System.Console.Write(args[0]);}}//
Try it online!
B: 438 + 18 bytes
class A{public static int i=0;}
class B{static void Main(string[]args){if(A.i<1){System.Console.Write(args[0]);return;}var a=@"class A{{public static int i=2;static void Main(string[]args){{System.Console.Write(args[0]);}}}}//class A{{public static int i=0;}}
class B{{static void Main(string[]args){{if(A.i<1){{System.Console.Write(args[0]);return;}}var a=@{0}{1}{0};System.Console.Write(a,'{0}',a);}}}}";System.Console.Write(a,'"',a);}}
Try it online!
A+B: 533 + 18 bytes
class A{public static int i=2;static void Main(string[]args){System.Console.Write(args[0]);}}//class A{public static int i=0;}
class B{static void Main(string[]args){if(A.i<1){System.Console.Write(args[0]);return;}var a=@"class A{{public static int i=2;static void Main(string[]args){{System.Console.Write(args[0]);}}}}//class A{{public static int i=0;}}
class B{{static void Main(string[]args){{if(A.i<1){{System.Console.Write(args[0]);return;}}var a=@{0}{1}{0};System.Console.Write(a,'{0}',a);}}}}";System.Console.Write(a,'"',a);}}
Try it online!
A and B take input as a command-line argument. A+B ignores any input. 18 bytes on B and A+B are added for the /p:StartupObject=B
option sent to MSBuild. It's only strictly necessary on A+B, but it seemed like cheating to not also have it in B. This way, the compiler flags for A+B are the compiler flags for A (none) plus the compiler flags for B.
Explanation
Program A is straightforward. Class A contains an (unused) static variable i
initialized to 2
, and prints its first argument when run. The //
at the end is important for the A+B code, but does nothing in A itself.
Program B is weird in isolation, but essentially the same. It creates a Class A containing a static variable i
initialized to 0
, and then runs the Main method of Class B, which does the same as Program A because A.i
is less than 1, and returns before any of the weird stuff. The newlines aren't necessary here, but are important for A+B.
When combined, the //
from Program A comments out the Class A declaration from Program B, but because of the newline Class B is fine, allowing A.i
to refer to the 2
value from Program A instead. The Compiler Flag makes the Program run B.Main() since A.Main() also exists. The result is that Program A+B does not output its argument, but instead goes to the following segment of B.Main(), which is basically just the standard C# quine.
I don't think you should have the A and B can be same program rule – Muhammad Salman – 2018-06-01T16:42:33.213
2@MuhammadSalman My original idea was to have a cat program be doubled to turn into a quine. I just wanted to open the door to easier solutions because I wasn't entirely sure it was possible. Looks like I was wrong on both counts, but I'm fine with that. – Beefster – 2018-06-01T16:46:53.403
3You should probably add that
AB
must be non-empty, since lots of languages have a 0-byte cat allowing for a 0-byte quine. – James – 2018-06-01T16:50:56.8779@DJMcMayhem a 0-byte quine wouldn't be a valid quine though. – Nissa – 2018-06-01T16:52:20.467
4What is a cat program? – Pedro A – 2018-06-01T22:21:34.613
@Hamsterrific: a program that prints its own input byte-for-byte – Beefster – 2018-06-01T22:42:21.707