Abgetrennt von Nullable für Referenztypen
Hallo,
ich habe folgendes Problem:
public class Foo
{
[...]
public void Add<T>(T item)
where T : class //damit item auch null sein kann
{
[...]
}
[...]
}
public static class Program
{
public void Main(params string[] args)
{
var foo = new Foo();
foo.Add<SomeClass>(new SomeClass());
foo.Add<int?>(4);
foo.Add<int?>(null);
}
}
Nun ist Nullable<T> nun mal ein struct, kann selbst also nicht null sein.
Fehlermeldung:
The type 'int?' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Foo.Add<T>(T item)'.
Mein Lösungsansatz: eine eigene Klasse nach dem Vorbild von Nullable bauen.
Irgendwie glaube ich, dass das auch nicht zum Ziel führt.
Vorschläge, eure Gedanken?
MfG
Tilton
"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra
Moin,
foo.Add<int?>(new int?(4));
geht das auch nicht?
Ciao:
GG 😉
Ciao:
GG 😉
Dumme Frage,
aber warum lässt Du das Constraint nicht ganz weg? Wenn eh alles als item übergeben werden kann. Allerdings sehe ich in diesem Konstrukt gar keinen Sinn, in Sachen Typsicherheit.
LG, Marko
Hallo,
na ja das ganze Konstrukt ist auch deutlich komplexer. Das Constraint hab ich mittlerweile auch schon ausgebaut.
Sinn war egl. das innerhalb der Klasse Foo Add<T>(null);
schreiben kann. Hab das jetzt durch Add<T>(default(T))
ersetzt.
Die Aufgabe des Constraint war egl. eben nur vollwertige "Nullable"s überhaupt zu gelassen sind.
Ohne dieses Constraint könnte Jimmy jetzt auch Werte-Typen verwenden, was der gesammten Hilfsklasse den Sinn nimmt.
MfG
"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra
Dumme Frage,
aber warum lässt Du das Constraint nicht ganz weg? Wenn eh alles als item übergeben werden kann. Allerdings sehe ich in diesem Konstrukt gar keinen Sinn, in Sachen Typsicherheit.
LG, Marko
Stimmt, du willst einschränken aber doch alles zulassen. Ohne Constraint funktionierts wunderbar:
static void Main(string[] args)
{
Foo(5);
Foo((int?)5);
Foo((int?)null);
Foo("bar");
Foo((string)null);
}
static void Foo<T>(T item)
{
if (ReferenceEquals(item, null))
Console.WriteLine("Item is null");
else Console.WriteLine(item);
}
Oder willst du was anderes erreichen?
Lg, XXX
Ich wollte alle NICHT-Nullable<T> Werte-Typen verbieten, sprich erzwingen das man bspw. int? nutzen muss und int nicht.
EDIT: Gleichzeitig aber auch alle normalen Klassen.
MfG
Tilton
"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra
Dann wird wohl eine Überladung herhalten müssen. 😃
static void Main(string[] args)
{
//Foo(5); //error
Foo((int?)5);
Foo((int?)null);
Foo("bar");
Foo((string)null);
}
static void Foo<T>(T item) where T:class
{
if (ReferenceEquals(item, null))
Console.WriteLine("Item is null");
else Console.WriteLine(item);
}
static void Foo<T>(T? item)where T:struct
{
if (ReferenceEquals(item, null))
Console.WriteLine("Item is null");
else Console.WriteLine(item);
}
Lg, XXX
Wäre mgl, ja. Aber mit T wird intern eine Klasse (ich nenn die jetzt mal) Bar<T> angelegt.
🤔
BarStruct<T> : IBar where T : struct { }
BarClass<T> : IBar where T : class { }
🤔
na ja ... mit dem Gedanken muss ich erst ma' bissel schwanger gehn.
Danke
"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra
Wenn es ausschließlich intern verwendet wird, kannst du ja auch einfach object verwenden? So wie ich das verstehe, willst du einfach die Handhabung mit dem Generic Constraints einschränken. Das machen die zwei Methoden auch. Wie du die Objekte intern behandelst ist dann wieder eine andere Geschichte.
Lg, XXX
Ich wollte alle NICHT-Nullable<T> Werte-Typen verbieten[...] Gleichzeitig aber auch alle normalen Klassen.
Dann schreibe das Nullable<T> einfach aus und setze ein Constraint auf struct
, also:
public void Add<T>(Nullable<T> item)
where T : struct
{
[...]
}
Der Fehlerteufel
Gleichzeitig aber auch alle normalen Klassen.
-> hätte sein müssen:
Gleichzeitig aber auch alle normalen Klassen erlauben.
Ich seh schon muss etwas mehr ausholen.
internal class Bar<T> : IEnumerable<T> : IBar
{
[...]
public void Add(T item) { [...] }
void IBar.Add(object item)
{
if (item is T)
this.Add((T)item);
else
throw new InvalidOperationException("wrong type.");
}
Type IBar.BarType { get { return typeof(T); } }
[...]
}
public interface IBar : IEnumerable
{
[...]
void Add(object item);
Type BarType { get; }
[...]
}
public class Foo : IEnumerable<IBar>
{
[...]
private IList<IBar> bars = new List<IBar>();
public void AddNewBar<T>()
{
this.bars.add(new Bar<T>());
}
public void Add(int index, object item)
{
this.bars[index].Add(item);
}
public Type[] GetBarTypes()
{
var array = new Type[this.bars.Count];
for (int i = 0; i < array.Length; i++)
{
array[i] = this.bars[i].BarType;
}
return array;
}
[...]
}
Ich hoffe nun wird es etwas klarer.
Die Idee mit
BarStruct<T> : IBar where T : struct { }
BarClass<T> : IBar where T : class { }
is da dann schon hilfreich und könnte der Weg zu Lösung sein.
MfG
Tilton
"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra
Leider verstehe ich noch immer nicht was du damit bezwecken willst. Ich kann mir nicht vorstellen in welchem Szenario ich eine generische Klasse brauche, die aber ein nicht generisches Interface implementiert.
Du musst darauf nicht eingehen. Ich kann nur nichts weiteres dazu beitragen da ich den Sinn und Zweck deines Vorhabens nicht verstehe.
Lg, XXX
Um die Verwirrung hoffentlich aufzulösen, habe ich mal die Klassendiagramme der eigentlichen Implementierung hochgeladen.
Wie man da sehn kann wird aus Foo -> Table und aus Bar -> Column.
Das Konzept is also so ne art DB-Table aber mit .Net-Datentypen (deswegen auch kein DataTable).
Jede Spalte hat ihren eigen Datentyp. Man könnte auch einfach alles ohne generic lösen, aber dann müsste man sich irgendwie anders drum kümmern, dass jede Spalte nur mit dem jeweilig richtigen Datentyp bestückt wird.
MfG
TiltonJH
"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra