using System; using System.Linq; using System.Collections; using System.Collections.Generic; using System.Reflection; public class Program { static void Main(string[] args) { object x = 2; var a = new A(); a.Val = x; a.array = new A[3] { a, new A() { Val = "a"}, null}; var b = new A(); b.Val = x; b.array = new A[3] { b, new A() { Val = "a"}, null}; a.array[2] = b; b.array[2] = b; Console.WriteLine(string.Join("\n", FindStringValues(a).ToArray())); } public class A { public A[] array {get;set;} public object Val {get;set;} } private static IEnumerable FindStringValues(object obj) { return _FindStringValues(obj, new List()); } private static IEnumerable _FindStringValues(object obj, IList visitedObjects) { if (obj == null) yield break; // Console.WriteLine(string.Join("; ", visitedObjects.Select(i => i.ToString()).ToArray())); if (visitedObjects.Any(item => Object.ReferenceEquals(item, obj))) yield break; if (!(obj is string)) visitedObjects.Add(obj); Type type = obj.GetType(); if (type == typeof(string)) { yield return (obj).ToString(); yield break; } if (typeof(IEnumerable).IsAssignableFrom(type)) { var array = obj as IEnumerable; foreach (var item in array) foreach (var str in _FindStringValues(item, visitedObjects)) yield return str; yield break; } if (type.IsClass) { FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (FieldInfo field in fields) { object item = field.GetValue(obj); if (item == null) continue; foreach (var str in _FindStringValues(item, visitedObjects)) yield return str; } yield break; } } }