5 // Patrik Torstensson (patrik.torstensson@labs2.com)
6 // Jeffrey Stedfast (fejj@ximian.com)
7 // Dan Lewis (dihlewis@yahoo.co.uk)
9 // (C) 2001 Ximian, Inc. http://www.ximian.com
14 using System.Collections;
15 using System.Globalization;
16 using System.Runtime.CompilerServices;
20 public sealed class String : IConvertible, IComparable, ICloneable, IEnumerable {
23 public static readonly String Empty = "";
25 [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)]
26 unsafe public extern String(char *value);
28 [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)]
29 unsafe public extern String(char *value, int sindex, int length);
31 [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)]
32 unsafe public extern String(sbyte *value);
34 [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)]
35 unsafe public extern String(sbyte *value, int sindex, int length);
37 [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)]
38 unsafe public extern String(sbyte *value, int sindex, int length, Encoding enc);
40 [MethodImplAttribute(MethodImplOptions.InternalCall)]
41 public extern String(char [] val, int sindex, int length);
43 [MethodImplAttribute(MethodImplOptions.InternalCall)]
44 public extern String(char [] val);
46 [MethodImplAttribute(MethodImplOptions.InternalCall)]
47 public extern String(char c, int count);
49 [MethodImplAttribute(MethodImplOptions.InternalCall)]
50 public extern override int GetHashCode();
52 public static bool Equals(String str1, String str2) {
53 if ((Object) str1 == (Object) str2)
56 if (null == (Object) str1 || null == (Object) str2)
59 if (str1.length != str2.length)
62 return InternalEquals(str1, str2);
65 public static bool operator == (String str1, String str2) {
66 return Equals(str1, str2);
69 public static bool operator != (String str1, String str2) {
70 return !Equals(str1, str2);
73 public override bool Equals(Object obj) {
80 return InternalEquals(this, (String) obj);
83 public bool Equals(String value) {
87 if (length != value.length)
90 return InternalEquals(this, value);
93 [IndexerName("Chars")]
94 public extern char this[int index] {
95 [MethodImplAttribute(MethodImplOptions.InternalCall)]
99 public Object Clone() {
103 public TypeCode GetTypeCode () {
104 return TypeCode.String;
107 public void CopyTo(int sindex, char[] dest, int dindex, int count) {
108 // LAMESPEC: should I null-terminate?
111 throw new ArgumentNullException();
113 if (sindex < 0 || dindex < 0 || count < 0)
114 throw new ArgumentOutOfRangeException ();
116 if (sindex + count > Length)
117 throw new ArgumentOutOfRangeException ();
119 if (dindex + count > dest.Length)
120 throw new ArgumentOutOfRangeException ();
122 InternalCopyTo(sindex, dest, dindex, count);
125 public char[] ToCharArray() {
126 return ToCharArray(0, length);
129 public char[] ToCharArray(int sindex, int length) {
130 if (sindex < 0 || length < 0 || sindex + length > this.length)
131 throw new ArgumentOutOfRangeException ();
133 char [] tmp = new char[length];
135 InternalCopyTo(sindex, tmp, 0, length);
140 public String [] Split(params char [] separator) {
141 return Split(separator, Int32.MaxValue);
144 public String[] Split(char[] separator, int count) {
145 if (null == separator) {
146 separator = WhiteChars;
150 throw new ArgumentOutOfRangeException ();
153 return new String[0];
156 return new String[1] { ToString() };
158 return InternalSplit(separator, count);
161 public String Substring (int sindex) {
162 if (sindex < 0 || sindex > this.length) {
163 throw new ArgumentOutOfRangeException();
166 string tmp = InternalAllocateStr(this.length - sindex);
167 InternalStrcpy(tmp, 0, this, sindex, length - sindex);
172 public String Substring (int sindex, int length) {
173 if (length < 0 || sindex < 0 || sindex + length > this.length) {
174 throw new ArgumentOutOfRangeException();
180 string tmp = InternalAllocateStr(length);
181 InternalStrcpy(tmp, 0, this, sindex, length);
186 private static readonly char[] WhiteChars = { (char) 0x9, (char) 0xA, (char) 0xB, (char) 0xC, (char) 0xD, (char) 0x20, (char) 0xA0, (char) 0x2000, (char) 0x2001, (char) 0x2002, (char) 0x2003, (char) 0x2004, (char) 0x2005,
187 (char) 0x2006, (char) 0x2007, (char) 0x2008, (char) 0x2009, (char) 0x200A, (char) 0x200B, (char) 0x3000, (char) 0xFEFF };
189 public String Trim(params char[] chars) {
190 if (null == chars || chars.Length == 0)
193 return InternalTrim(chars, 0);
196 public String TrimStart(params char[] chars) {
197 if (null == chars || chars.Length == 0)
200 return InternalTrim(chars, 1);
203 public String TrimEnd(params char[] chars) {
204 if (null == chars || chars.Length == 0)
207 return InternalTrim(chars, 2);
210 public static int Compare(String s1, String s2) {
211 return Compare(s1, s2, false);
214 public static int Compare(String s1, String s2, bool inCase) {
220 } else if (null == s2)
223 return InternalCompare(s1, 0, s2, 0, Math.Max(s1.length, s2.length), inCase);
227 public static int Compare(String s1, String s2, bool inCase, CultureInfo culture) {
228 return Compare(s1, s2, inCase);
231 public static int Compare(String s1, int i1, String s2, int i2, int length) {
232 return Compare(s1, i1, s2, i2, length, false);
235 public static int Compare(String s1, int i1, String s2, int i2, int length, bool inCase) {
241 } else if (null == s2)
244 if (length < 0 || i1 < 0 || i2 < 0)
245 throw new ArgumentOutOfRangeException ();
247 if (i1 > s1.length || i2 > s2.length)
248 throw new ArgumentOutOfRangeException ();
253 return InternalCompare(s1, i1, s2, i2, length, inCase);
257 public static int Compare(String s1, int i1, String s2, int i2, int length, bool inCase, CultureInfo culture) {
258 return Compare(s1, i1, s2, i2, length, inCase);
261 public int CompareTo(Object value) {
265 if (!(value is String))
266 throw new ArgumentException();
268 return String.Compare(this, (String) value, false);
271 public int CompareTo(String str) {
275 return Compare(this, str, false);
278 public static int CompareOrdinal(String s1, String s2) {
279 if (null == s1 || null == s2) {
280 if ((Object)s1 == (Object) s2) {
284 return (s1 == null) ? -1 : 1;
287 return InternalCompare(s1, 0, s2, 0, Math.Max(s1.length, s2.length), false);
290 public static int CompareOrdinal(String s1, int i1, String s2, int i2, int length) {
291 if (null == s1 || null == s2) {
292 if ((Object)s1 == (Object) s2) {
296 return (s1 == null) ? -1 : 1;
299 if (i1 < 0 || i2 < 0 || length < 0)
300 throw new ArgumentOutOfRangeException ();
302 if (i1 > s1.length || i2 > s2.length)
303 throw new ArgumentOutOfRangeException ();
305 return InternalCompare(s1, i1, s2, i2, length, false);
308 public bool EndsWith(String value) {
310 throw new ArgumentNullException();
312 if (value.length > this.length) {
316 return (0 == Compare(this, length - value.length, value, 0, value.length));
319 public int IndexOfAny(char [] arr) {
321 throw new ArgumentNullException();
323 return InternalIndexOfAny(arr, 0, this.length);
326 public int IndexOfAny(char [] arr, int sindex) {
328 throw new ArgumentNullException();
329 if (sindex < 0 || sindex >= this.length)
330 throw new ArgumentOutOfRangeException();
332 return InternalIndexOfAny(arr, sindex, this.length - sindex);
335 public int IndexOfAny(char [] arr, int sindex, int count) {
337 throw new ArgumentNullException();
338 if (sindex < 0 || count < 0 || sindex + count > this.length)
339 throw new ArgumentOutOfRangeException ();
341 return InternalIndexOfAny(arr, sindex, count);
344 public int IndexOf(char value) {
345 return InternalIndexOf(value, 0, this.length);
348 public int IndexOf(String value) {
349 return IndexOf(value, 0, this.length);
352 public int IndexOf(char value, int sindex) {
353 if (sindex < 0 || sindex >= this.length) {
354 throw new ArgumentOutOfRangeException();
357 return InternalIndexOf(value, sindex, this.length - sindex);
360 public int IndexOf(String value, int sindex) {
361 return IndexOf(value, sindex, this.length - sindex);
364 public int IndexOf(char value, int sindex, int count) {
365 if (sindex < 0 || count < 0 || sindex + count > this.length)
366 throw new ArgumentOutOfRangeException ();
368 if (sindex == 0 && this.length == 0)
371 return InternalIndexOf(value, sindex, count);
374 public int IndexOf(String value, int sindex, int count) {
376 throw new ArgumentNullException();
378 if (sindex < 0 || count < 0 || sindex + count > this.length)
379 throw new ArgumentOutOfRangeException ();
381 if (sindex == 0 && this.length == 0)
384 return InternalIndexOf(value, sindex, count);
387 public int LastIndexOfAny(char [] arr) {
389 throw new ArgumentNullException();
391 return InternalLastIndexOfAny(arr, this.length - 1, this.length);
394 public int LastIndexOfAny(char [] arr, int sindex) {
396 throw new ArgumentNullException();
398 if (sindex < 0 || sindex > this.length)
399 throw new ArgumentOutOfRangeException();
401 if (this.length == 0)
404 return InternalLastIndexOfAny(arr, sindex, sindex + 1);
407 public int LastIndexOfAny(char [] arr, int sindex, int count) {
409 throw new ArgumentNullException();
411 if (sindex < 0 || count < 0 || sindex > this.length || sindex - count < -1)
412 throw new ArgumentOutOfRangeException();
414 if (this.length == 0)
417 return InternalLastIndexOfAny(arr, sindex, count);
420 public int LastIndexOf(char value) {
421 return InternalLastIndexOf(value, this.length - 1, this.length);
424 public int LastIndexOf(String value) {
426 throw new ArgumentNullException();
428 if (value.length == 0)
431 if (this.length == 0)
434 return InternalLastIndexOf(value, this.length - 1, this.length);
437 public int LastIndexOf(char value, int sindex){
438 return LastIndexOf(value, sindex, sindex + 1);
441 public int LastIndexOf(String value, int sindex) {
442 return LastIndexOf(value, sindex, sindex + 1);
445 public int LastIndexOf(char value, int sindex, int count) {
446 if (sindex < 0 || count < 0)
447 throw new ArgumentOutOfRangeException ();
449 if (sindex >= this.length || sindex - count + 1 < 0)
450 throw new ArgumentOutOfRangeException ();
452 if (sindex == 0 && this.length == 0)
455 return InternalLastIndexOf(value, sindex, count);
458 public int LastIndexOf(String value, int sindex, int count) {
460 throw new ArgumentNullException();
462 if (sindex < 0 || sindex > this.length)
463 throw new ArgumentOutOfRangeException ();
465 if (count < 0 || sindex - count + 1 < 0)
466 throw new ArgumentOutOfRangeException ();
468 if (value.length > sindex)
471 if (value == String.Empty)
474 if (sindex == 0 && this.length == 0)
477 return InternalLastIndexOf(value, sindex, count);
480 public String PadLeft(int width) {
481 return PadLeft(width, ' ');
484 public String PadLeft(int width, char chr) {
486 throw new ArgumentException();
488 if (width < this.length)
489 return String.Copy(this);
491 return InternalPad(width, chr, false);
494 public String PadRight(int width) {
495 return PadRight(width, ' ');
498 public String PadRight(int width, char chr) {
500 throw new ArgumentException();
502 if (width < this.length)
503 return String.Copy(this);
505 return InternalPad(width, chr, true);
508 public bool StartsWith(String value) {
510 throw new ArgumentNullException();
512 if (this.length < value.length)
515 return (0 == Compare(this, 0, value, 0 , value.length));
519 public String Replace (char oldChar, char newChar) {
520 return InternalReplace(oldChar, newChar);
523 public String Replace(String oldValue, String newValue) {
524 if (null == oldValue)
525 throw new ArgumentNullException();
527 return InternalReplace(oldValue, newValue);
530 public String Remove(int sindex, int count) {
531 if (sindex < 0 || count < 0 || sindex + count > this.length)
532 throw new ArgumentOutOfRangeException ();
534 return InternalRemove(sindex, count);
537 public String ToLower() {
538 return InternalToLower();
541 public String ToLower(CultureInfo culture) {
542 throw new NotImplementedException();
545 public String ToUpper() {
546 return InternalToUpper();
549 public String ToUpper(CultureInfo culture) {
550 throw new NotImplementedException();
553 public override String ToString() {
557 public String ToString(IFormatProvider provider) {
561 public String Trim() {
565 public static String Format(String format, Object arg0) {
566 return Format(null, format, new Object[] {arg0});
569 public static String Format(String format, Object arg0, Object arg1) {
570 return Format(null, format, new Object[] {arg0, arg1});
573 public static String Format(String format, Object arg0, Object arg1, Object arg2) {
574 return Format(null, format, new Object[] {arg0, arg1, arg2});
577 public static string Format (string format, params object[] args) {
578 return Format (null, format, args);
581 public static string Format (IFormatProvider provider, string format, params object[] args) {
582 if (format == null || args == null)
583 throw new ArgumentNullException ();
585 StringBuilder result = new StringBuilder ();
589 while (ptr < format.length) {
590 char c = format[ptr ++];
593 result.Append (format, start, ptr - start - 1);
595 // check for escaped open bracket
597 if (format[ptr] == '{') {
608 ParseFormatSpecifier (format, ref ptr, out n, out width, out left_align, out arg_format);
609 if (n >= args.Length)
610 throw new FormatException ("Index (zero based) must be greater than or equal to zero and less than the size of the argument list.");
614 object arg = args[n];
619 else if (arg is IFormattable)
620 str = ((IFormattable)arg).ToString (arg_format, provider);
622 str = arg.ToString ();
624 // pad formatted string and append to result
626 if (width > str.length) {
627 string pad = new String (' ', width - str.length);
643 else if (c == '}' && format[ptr] == '}') {
644 result.Append (format, start, ptr - start - 1);
649 if (start < format.length)
650 result.Append (format.Substring (start));
652 return result.ToString ();
655 public static String Copy (String str) {
657 throw new ArgumentNullException ();
659 int length = str.length;
661 String tmp = InternalAllocateStr(length);
662 InternalStrcpy(tmp, 0, str);
666 public static String Concat(Object obj) {
670 return obj.ToString();
673 public static String Concat(Object obj1, Object obj2) {
680 return Concat(obj1.ToString(), obj2.ToString());
683 public static String Concat(Object obj1, Object obj2, Object obj3) {
693 return Concat(obj1.ToString(), obj2.ToString(), obj3.ToString());
697 // I can not find the "__arglist" argument on the spec
700 [CLSCompliant(false)]
701 public static String Concat (Object arg0, Object arg1, Object arg2, Object arg3, __arglist) {
702 throw new NotImplementedException();
706 public static String Concat(String s1, String s2) {
708 if (null == s2) { return String.Empty; }
712 if (null == s2) { return s1; }
714 String tmp = InternalAllocateStr(s1.length + s2.length);
716 InternalStrcpy(tmp, 0, s1);
717 InternalStrcpy(tmp, s1.length, s2);
722 public static String Concat(String s1, String s2, String s3) {
723 if (null == s1 && null == s2 && null == s3) {
727 if (null == s1) { s1 = String.Empty; }
728 if (null == s2) { s2 = String.Empty; }
729 if (null == s3) { s3 = String.Empty; }
731 String tmp = InternalAllocateStr(s1.length + s2.length + s3.length);
733 InternalStrcpy(tmp, 0, s1);
734 InternalStrcpy(tmp, s1.length, s2);
735 InternalStrcpy(tmp, s1.length + s2.length, s3);
740 public static String Concat(String s1, String s2, String s3, String s4) {
741 if (null == s1 && null == s2 && null == s3 && null == s4) {
745 if (null == s1) { s1 = String.Empty; }
746 if (null == s2) { s2 = String.Empty; }
747 if (null == s3) { s3 = String.Empty; }
748 if (null == s4) { s4 = String.Empty; }
750 String tmp = InternalAllocateStr(s1.length + s2.length + s3.length + s4.length);
752 InternalStrcpy(tmp, 0, s1);
753 InternalStrcpy(tmp, s1.length, s2);
754 InternalStrcpy(tmp, s1.length + s2.length, s3);
755 InternalStrcpy(tmp, s1.length + s2.length + s3.length, s4);
760 public static String Concat(params Object[] args) {
762 int len, i, currentpos;
765 throw new ArgumentNullException ();
767 strings = new string [args.Length];
770 foreach (object arg in args) {
771 /* use Empty for each null argument */
773 strings[i] = String.Empty;
775 strings[i] = arg.ToString ();
776 len += strings[i].length;
785 String tmp = InternalAllocateStr(len);
786 for (i = 0; i < strings.Length; i++) {
787 InternalStrcpy(tmp, currentpos, strings[i]);
788 currentpos += strings[i].length;
794 public static String Concat(params String[] values) {
795 int len, i, currentpos;
798 throw new ArgumentNullException ();
801 foreach (string value in values)
802 len += value != null ? value.length : 0;
809 String tmp = InternalAllocateStr(len);
810 for (i = 0; i < values.Length; i++) {
811 if (values[i] == null)
814 InternalStrcpy(tmp, currentpos, values[i]);
815 currentpos += values[i].length;
821 public String Insert(int sindex, String value) {
823 throw new ArgumentNullException();
825 if (sindex < 0 || sindex > this.length)
826 throw new ArgumentOutOfRangeException();
828 return InternalInsert(sindex, value);
832 public static string Intern (string str) {
834 throw new ArgumentNullException ();
836 return InternalIntern(str);
839 public static string IsInterned (string str) {
841 throw new ArgumentNullException();
843 return InternalIsInterned(str);
846 public static string Join (string separator, string [] value) {
848 throw new ArgumentNullException ();
850 return Join(separator, value, 0, value.Length);
853 public static string Join(string separator, string[] value, int sindex, int count) {
855 throw new ArgumentNullException ();
857 if (sindex + count > value.Length)
858 throw new ArgumentOutOfRangeException ();
860 if (sindex == value.Length)
863 return InternalJoin(separator, value, sindex, count);
866 bool IConvertible.ToBoolean (IFormatProvider provider) {
867 return Convert.ToBoolean (this);
870 byte IConvertible.ToByte (IFormatProvider provider) {
871 return Convert.ToByte (this);
874 char IConvertible.ToChar (IFormatProvider provider) {
875 return Convert.ToChar (this);
878 DateTime IConvertible.ToDateTime (IFormatProvider provider) {
879 return Convert.ToDateTime (this);
882 decimal IConvertible.ToDecimal (IFormatProvider provider) {
883 return Convert.ToDecimal (this);
886 double IConvertible.ToDouble (IFormatProvider provider) {
887 return Convert.ToDouble (this);
890 short IConvertible.ToInt16 (IFormatProvider provider) {
891 return Convert.ToInt16 (this);
894 int IConvertible.ToInt32 (IFormatProvider provider) {
895 return Convert.ToInt32 (this);
898 long IConvertible.ToInt64 (IFormatProvider provider) {
899 return Convert.ToInt64 (this);
902 [CLSCompliant(false)]
903 sbyte IConvertible.ToSByte (IFormatProvider provider) {
904 return Convert.ToSByte (this);
907 float IConvertible.ToSingle (IFormatProvider provider) {
908 return Convert.ToSingle (this);
910 string IConvertible.ToString (IFormatProvider format) {
914 object IConvertible.ToType (Type conversionType, IFormatProvider provider) {
915 return Convert.ToType (this, conversionType, provider);
918 [CLSCompliant(false)]
919 ushort IConvertible.ToUInt16 (IFormatProvider provider) {
920 return Convert.ToUInt16 (this);
923 [CLSCompliant(false)]
924 uint IConvertible.ToUInt32 (IFormatProvider provider) {
925 return Convert.ToUInt32 (this);
928 [CLSCompliant(false)]
929 ulong IConvertible.ToUInt64 (IFormatProvider provider) {
930 return Convert.ToUInt64 (this);
933 TypeCode IConvertible.GetTypeCode () {
934 return TypeCode.String;
943 public CharEnumerator GetEnumerator () {
944 return new CharEnumerator (this);
947 IEnumerator IEnumerable.GetEnumerator () {
948 return new CharEnumerator (this);
951 private static void ParseFormatSpecifier (string str, ref int ptr, out int n, out int width, out bool left_align, out string format) {
952 // parses format specifier of form:
958 // N = argument number (non-negative integer)
960 n = ParseDecimal (str, ref ptr);
962 throw new FormatException ("Input string was not in correct format.");
964 // M = width (non-negative integer)
966 if (str[ptr] == ',') {
967 left_align = (str[++ ptr] == '-');
971 width = ParseDecimal (str, ref ptr);
973 throw new FormatException ("Input string was not in correct format.");
980 // F = argument format (string)
982 if (str[ptr] == ':') {
984 while (str[ptr] != '}')
987 format = str.Substring (start, ptr - start);
992 if (str[ptr ++] != '}')
993 throw new FormatException ("Input string was not in correct format.");
995 catch (IndexOutOfRangeException) {
996 throw new FormatException ("Input string was not in correct format.");
1000 private static int ParseDecimal (string str, ref int ptr) {
1005 if (c < '0' || '9' < c)
1008 n = n * 10 + c - '0';
1019 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1020 private extern static string InternalJoin(string separator, string[] value, int sindex, int count);
1022 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1023 private extern String InternalInsert(int sindex, String value);
1025 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1026 private extern String InternalReplace(char oldChar, char newChar);
1028 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1029 private extern String InternalReplace(String oldValue, String newValue);
1031 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1032 private extern String InternalRemove(int sindex, int count);
1034 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1035 private extern void InternalCopyTo(int sindex, char[] dest, int dindex, int count);
1037 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1038 private extern String[] InternalSplit(char[] separator, int count);
1040 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1041 private extern String InternalTrim(char[] chars, int typ);
1043 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1044 private extern int InternalIndexOf(char value, int sindex, int count);
1046 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1047 private extern int InternalIndexOf(string value, int sindex, int count);
1049 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1050 private extern int InternalIndexOfAny(char [] arr, int sindex, int count);
1052 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1053 private extern int InternalLastIndexOf(char value, int sindex, int count);
1055 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1056 private extern int InternalLastIndexOf(String value, int sindex, int count);
1058 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1059 private extern int InternalLastIndexOfAny(char [] anyOf, int sindex, int count);
1061 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1062 private extern String InternalPad(int width, char chr, bool right);
1064 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1065 private extern String InternalToLower();
1067 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1068 private extern String InternalToUpper();
1070 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1071 private extern static String InternalAllocateStr(int length);
1073 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1074 private extern static void InternalStrcpy(String dest, int destPos, String src);
1076 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1077 private extern static void InternalStrcpy(String dest, int destPos, String src, int startPos, int count);
1079 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1080 private extern static string InternalIntern(string str);
1082 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1083 private extern static string InternalIsInterned(string str);
1085 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1086 private extern static int InternalCompare(String s1, int i1, String s2, int i2, int length, bool inCase);
1088 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1089 private extern static bool InternalEquals(String s1, String s2);