473,760 Members | 10,633 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Generic Collections and inheritance (again)

I ran into a problem a while back when attempting to convert existing .NET
1.1 based code to .NET 2.0 using Generic collections rather than Hashtable,
ArrayList, etc.

I ran into an issue because the old code allowed me to do what basically was
the following assignment:
class SomeClass
{
private Queue q;
SomeClass(Queue q)
{
this.q = q;
}
}

class SomeOtherClass : SomeClass
{
SomeOtherClass( Queue q) : base(q)
{
}
}
Where, when converted to generics is actually:
class SomeClass
{
private Queue<A> q;
SomeClass(Queue <A> q)
{
this.q = q;
}
}

class SomeOtherClass : SomeClass
{
SomeOtherClass( Queue<SubClasso fA> q) : base(q)
{
}
}

Unfortunately Queeu<SubClasso fA> cannot be passed to a Queue<A>.

Now, I was able to resolve the problem in this case by turning the class
which took this into a generic class itself:
class SomeClass<T> where T : A
and
class SomeOtherClass : SomeClass<SubCl assofA>
However, I've now run into essentially the same situation with another
class. I do not believe I can use the same thing here though. The list
(Dictionary, actually) being passed into the class constructor could contain
various subclasses - not just one. Using the above solution of
class SomeOtherClass : SomeClass<SubCl assofA>
limits me to ONLY using SubClassofA objects. But in this case there are
SEVERAL subclasses of A. I can guarrantee that the Dictionary here is ONLY
used in a "read" sense (the Dictionary is not altered). In fact, the only
time the list is used is to retrieve an element (which it currently expects
to be of type A). Various operations are then performed on that object, but
the list itself is never changed.

Does that "read-only" aspect buy me any alternatives?
As I see it now, my only option is to go back to the original Hashtable
object rather than Dictionary.

--
Adam Clauss

Mar 3 '06 #1
4 2223
Is there anything stopping you from just accepting the superclass A?

Mar 3 '06 #2
Yes - the fact that the original source is a Dictionary of SubclassOfA -
that Dictionary cannot simply be "passed" into a Dictionary of A. (Keys in
both cases are strings).

--
Adam Clauss

"Andy" <aj*****@alum.r it.edu> wrote in message
news:11******** *************@p 10g2000cwp.goog legroups.com...
Is there anything stopping you from just accepting the superclass A?

Mar 3 '06 #3


Adam Clauss wrote:
Unfortunately Queeu<SubClasso fA> cannot be passed to a Queue<A>.
Well it's not really unfortunate -- it preseves static type-safety,
consider the following:

Queue<SubA> subaq = new Queue<SubA>();
Queue<A> aq = subaq;
aq.Enque(new A()); // oops ;)
Now, I was able to resolve the problem in this case by turning the class
which took this into a generic class itself:
class SomeClass<T> where T : A
and
class SomeOtherClass : SomeClass<SubCl assofA>
I use adapters for ICollection, assuming Bar is a subtype of Foo:

ICollection<Bar > bars = ...;
ICollection<Foo > = new UpcastedCollect ion<Bar,Foo>(ba rs);

However, I've now run into essentially the same situation with another
class. I do not believe I can use the same thing here though. The list
(Dictionary, actually) being passed into the class constructor could contain
various subclasses - not just one. Using the above solution of
class SomeOtherClass : SomeClass<SubCl assofA>
limits me to ONLY using SubClassofA objects. But in this case there are
SEVERAL subclasses of A. I can guarrantee that the Dictionary here is ONLY
used in a "read" sense (the Dictionary is not altered). In fact, the only
time the list is used is to retrieve an element (which it currently expects
to be of type A). Various operations are then performed on that object, but
the list itself is never changed.

Does that "read-only" aspect buy me any alternatives?
Well, actually yes, it makes sure no runtime casts are required.
As I see it now, my only option is to go back to the original Hashtable
object rather than Dictionary.


Below are some adapters that shows what I mean and get you started on
writing your own adapters.

#region Immutable Exceptions
public class Immutable: InvalidOperatio nException {
public readonly object Instance;
protected Immutable(objec t instance): this(instance,
string.Format(" {0} is immutable", instance)) { }
protected Immutable(objec t instance, string msg): base(msg) {
this.Instance = instance; }
public static Immutable Make(object instance) { return new
Immutable(insta nce); }
public static Immutable<T> Make<T>(T instance) { return new
Immutable<T>(in stance); }
public static Immutable Make(object instance, string msg) { return
new Immutable(insta nce, msg); }
public static Immutable<T> Make<T>(T instance, string msg) { return
new Immutable<T>(in stance, msg); }
}
public class Immutable<T>: Immutable {
public readonly new T Instance;
public Immutable(T instance, string msg) : base(instance, msg) {
this.Instance = instance; }
public Immutable(T instance) : this(instance, string.Format(" {0} is
immutable", instance)) { }
}
#endregion

#region ICollection transformation
public class TransformedColl ection<T, R> : ICollection<R>
{
public delegate R Transformer(T t);
public readonly ICollection<T> Parent;
public readonly Transformer Transform;
public readonly TransformedColl ection<R, T>.Transformer Inverse;
protected T NoInverse(R r) { throw new
NotSupportedExc eption(string.F ormat("{0} does not implement {1}
Inverse({2})", this, typeof(T), typeof(R))); }
protected R NoTransform(T t) { throw new
NotSupportedExc eption(string.F ormat("{0} does not implement {1}
Transform({2})" , this, typeof(R), typeof(T))); }
public TransformedColl ection(ICollect ion<T> parent, Transformer
transform, TransformedColl ection<R, T>.Transformer inverse)
{
this.Parent = parent;
this.Transform = transform == null ? NoTransform : transform;
this.Inverse = inverse == null ? NoInverse : inverse;
}
public TransformedColl ection(ICollect ion<T> parent, Transformer
transform): this(parent, transform, null) {}
public TransformedColl ection(ICollect ion<T> parent,
TransformedColl ection<R,T>.Tra nsformer inverse) : this(parent, null,
inverse) { }
public void Add(R r) { Parent.Add(Inve rse(r)); }
public void Clear() { Parent.Clear(); }
public bool Contains(R r) { return Parent.Contains (Inverse(r)); }
public void CopyTo(R[] rs, int index) { foreach (T t in Parent)
rs[index++] = Transform(t); }
public bool Remove(R r) { return Parent.Remove(I nverse(r)); }
public int Count { get { return Parent.Count; } }
public bool IsReadOnly { get { return Parent.IsReadOn ly; } }
public IEnumerator<R> GetEnumerator() { foreach (T t in Parent)
yield return Transform(t); }
System.Collecti ons.IEnumerator
System.Collecti ons.IEnumerable .GetEnumerator( ) { return GetEnumerator() ; }
}
public class UpcastedCollect ion<T, R> : ICollection<R> where T: R
{
public readonly ICollection<T> Parent;
public UpcastedCollect ion(ICollection <T> parent) { this.Parent =
parent; }
public void Add(R r) { Parent.Add((T)r ); }
public void Clear() { Parent.Clear(); }
public bool Contains(R r) { return r is T &&
Parent.Contains ((T)r); }
public void CopyTo(R[] rs, int index) { foreach (T t in Parent)
rs[index++] = (R)t; }
public bool Remove(R r) { return r is T && Parent.Remove(( T)r); }
public int Count { get { return Parent.Count; } }
public bool IsReadOnly { get { return Parent.IsReadOn ly; } }
public IEnumerator<R> GetEnumerator() { foreach (T t in Parent)
yield return (R)t; }
System.Collecti ons.IEnumerator
System.Collecti ons.IEnumerable .GetEnumerator( ) { return GetEnumerator() ; }
}
public class AddItem<T> : ICollection<T>
{
public readonly ICollection<T> Parent;
public readonly T Item;
public readonly IEqualityCompar er<T> Comparer;
public AddItem(ICollec tion<T> parent, T item, IEqualityCompar er<T>
comparer)
{
this.Parent = parent;
this.Item = item;
this.Comparer = comparer == null ? EqualityCompare r<T>.Default :
comparer;
}
public void Add(T t) { Parent.Add(t); }
public bool Remove(T t)
{
if (!Parent.Remove (t))
throw Immutable.Make( this, string.Format(" Cannot remove item
{0}", t));
else
return false;
}
public void Clear() { throw Immutable.Make( this,
string.Format(" Cannot clear {0}", this)); }
public bool Contains(T t) { return Comparer.Equals (t, Item) ||
Parent.Contains (t); }
public int Count { get { return Parent.Count + 1; } }
public void CopyTo(T[] array, int index)
{
array[index++] = Item;
Parent.CopyTo(a rray, index);
}
public bool IsReadOnly { get { return Parent.IsReadOn ly; } }
public IEnumerator<T> GetEnumerator()
{
yield return Item;
foreach (T t in Parent)
yield return t;
}
System.Collecti ons.IEnumerator
System.Collecti ons.IEnumerable .GetEnumerator( ) { return GetEnumerator() ; }
}
#endregion

#region IDictionary transformation
public class TransformedDict ionary<K1, V1, K2, V2> : IDictionary<K2, V2>
{
public readonly IDictionary<K1, V1> Parent;
public readonly TransformedColl ection<K1, K2>.Transformer KeyTransform;
public readonly TransformedColl ection<K2, K1>.Transformer KeyInverse;
public TransformedColl ection<V1, V2>.Transformer ValueTransform;
public TransformedColl ection<V2, V1>.Transformer ValueInverse;
public K2 DefaultKeyTrans form(K1 key) { throw new
NotSupportedExc eption(string.F ormat("{0} does not implement {1}
KeyTransform({2 })", this, typeof(K2), typeof(K1))); }
public K1 DefaultKeyInver se(K2 key) { throw new
NotSupportedExc eption(string.F ormat("{0} does not implement {1}
KeyInversem({2} )", this, typeof(K1), typeof(K2))); }
public V2 DefaultValueTra nsform(V1 value) { throw new
NotSupportedExc eption(string.F ormat("{0} does not implement {1}
ValueTransform( {2})", this, typeof(K2), typeof(K1))); }
public V1 DefaultValueInv erse(V2 value) { throw new
NotSupportedExc eption(string.F ormat("{0} does not implement {1}
ValueInverse({2 })", this, typeof(K1), typeof(K2))); }
public TransformedDict ionary(
IDictionary<K1, V1> parent,
TransformedColl ection<K1, K2>.Transformer keyTransform,
TransformedColl ection<K2, K1>.Transformer keyInverse,
TransformedColl ection<V1, V2>.Transformer valueTransform,
TransformedColl ection<V2, V1>.Transformer valueInverse) {
this.Parent = parent;
this.KeyTransfo rm = keyTransform == null ? DefaultKeyTrans form :
keyTransform;
this.KeyInverse = keyInverse == null ? DefaultKeyInver se :
keyInverse;
this.ValueTrans form = valueTransform == null ?
DefaultValueTra nsform : valueTransform;
this.ValueInver se = valueInverse == null ? DefaultValueInv erse :
valueInverse;
}
public bool ContainsKey(K2 key) { return
Parent.Contains Key(KeyInverse( key)); }
public void Add(K2 key, V2 value) { Parent.Add(KeyI nverse(key),
ValueInverse(va lue)); }
public bool Remove(K2 key) { return Parent.Remove(K eyInverse(key)) ; }
public bool TryGetValue(K2 key, out V2 v2)
{
V1 v1;
bool found = Parent.TryGetVa lue(KeyInverse( key), out v1);
if (found)
v2 = ValueTransform( v1);
else
v2 = default(V2);
return found;
}
public V2 this[K2 key]
{
get { return ValueTransform( Parent[KeyInverse(key)]); }
set { Parent[KeyInverse(key)] = ValueInverse(va lue); }
}
public ICollection<K2> Keys { get { return new
TransformedColl ection<K1, K2>(Parent.Keys , KeyTransform, KeyInverse); } }
public ICollection<V2> Values { get { return new
TransformedColl ection<V1, V2>(Parent.Valu es, ValueTransform,
ValueInverse); } }
public void Clear() { Parent.Clear(); }
public void Add(KeyValuePai r<K2, V2> kvp) { Parent.Add(new
KeyValuePair<K1 , V1>(KeyInverse( kvp.Key), ValueInverse(kv p.Value))); }
public bool Contains(KeyVal uePair<K2, V2> kvp) { return
Parent.Contains (new KeyValuePair<K1 ,V1>(KeyInverse (kvp.Key),
ValueInverse(kv p.Value))); }
public void CopyTo(KeyValue Pair<K2, V2>[] kvps, int index)
{
foreach (KeyValuePair<K 2, V2> kvp in this)
kvps[index++] = kvp;
}
public bool Remove(KeyValue Pair<K2, V2> kvp) { return
Parent.Remove(n ew KeyValuePair<K1 ,V1>(KeyInverse (kvp.Key),
ValueInverse(kv p.Value))); }
public int Count { get { return Parent.Count; } }
public bool IsReadOnly { get { return Parent.IsReadOn ly; } }
public IEnumerator<Key ValuePair<K2, V2>> GetEnumerator()
{
foreach (KeyValuePair<K 1, V1> kvp in Parent)
yield return new KeyValuePair<K2 , V2>(KeyTransfor m(kvp.Key),
ValueTransform( kvp.Value));
}
System.Collecti ons.IEnumerator
System.Collecti ons.IEnumerable .GetEnumerator( ) { return GetEnumerator() ; }
}
public class FunctionDiction ary<K, V> : IDictionary<K, V>
{
public readonly ICollection<K> Keys;
public readonly TransformedColl ection<K, V>.Transformer Function;
public readonly IComparer<V> ValueComparer;
public FunctionDiction ary(
ICollection<K> keys,
TransformedColl ection<K, V>.Transformer function,
IComparer<V> valueComparer)
{
this.Keys = keys;
this.Function = function;
this.ValueCompa rer = valueComparer == null ? Comparer<V>.Def ault
: valueComparer;
}
public bool ContainsKey(K key) { return Keys.Contains(k ey); }
public void Add(K key, V value) { throw Immutable.Make( this); }
public bool Remove(K key) { throw Immutable.Make( this); }
public bool TryGetValue(K key, out V v)
{
bool found = Keys.Contains(k ey);
if (found)
v = Function(key);
else
v = default(V);
return found;
}
ICollection<K> IDictionary<K, V>.Keys { get { return Keys; } }
public ICollection<V> Values { get { return new
TransformedColl ection<K, V>(Keys, Function); } }
public V this[K key]
{
get
{
if (Keys.Contains( key))
return Function(key);
else
throw new KeyNotFoundExce ption(string.Fo rmat("{0} not in
{1}", key, this));
}
set { throw Immutable.Make( this); }
}
public void Add(KeyValuePai r<K, V> kvp) { throw Immutable.Make( this); }
public void Clear() { throw Immutable.Make( this); }
public bool Contains(KeyVal uePair<K, V> kvp) { return
Keys.Contains(k vp.Key) && ValueComparer.C ompare(Function (kvp.Key),
kvp.Value) == 0; }
public void CopyTo(KeyValue Pair<K, V>[] kvps, int index)
{
foreach (K key in Keys)
kvps[index++] = new KeyValuePair<K, V>(key, Function(key));
}
public bool Remove(KeyValue Pair<K, V> kvp) { throw
Immutable.Make( this); }
public int Count { get { return Keys.Count; } }
public bool IsReadOnly { get { return true; } }
public IEnumerator<Key ValuePair<K, V>> GetEnumerator()
{
foreach (K key in Keys)
yield return new KeyValuePair<K, V>(key, Function(key));
}
System.Collecti ons.IEnumerator
System.Collecti ons.IEnumerable .GetEnumerator( ) { return GetEnumerator() ; }
}
public class AddKeyValuePair <K, V> : IDictionary<K, V>
{
public readonly IDictionary<K, V> Parent;
public readonly K Key;
public V Value;
public readonly IEqualityCompar er<K> KeyComparer;
public readonly IEqualityCompar er<V> ValueComparer;
public AddKeyValuePair (IDictionary<K, V> parent, K key, V value,
IEqualityCompar er<K> keyComparer, IEqualityCompar er<V> valueComparer)
{
if (parent.Contain sKey(key))
throw new ArgumentExcepti on("parent contains key");
this.Parent = parent;
this.Key = key;
this.Value = value;
this.KeyCompare r = keyComparer == null ?
EqualityCompare r<K>.Default : keyComparer;
this.ValueCompa rer = valueComparer == null ?
EqualityCompare r<V>.Default : valueComparer;
}
public bool ContainsKey(K k) { return KeyComparer.Equ als(k, Key) ||
Parent.Contains Key(k); }
public void Add(K k, V v)
{
if (KeyComparer.Eq uals(k, Key))
throw new ArgumentExcepti on(string.Forma t("{0} already
contains {1}", this, k));
else
Parent.Add(k, v);
}
public bool Remove(K k)
{
if (KeyComparer.Eq uals(k, Key))
throw Immutable.Make( this, string.Format(" Cannot remove key:
{0}", k));
else
return Parent.Remove(k );
}
public bool TryGetValue(K k, out V v)
{
if ( KeyComparer.Equ als(k, Key) )
{
v = Value;
return true;
}
else
return Parent.TryGetVa lue(k, out v);
}
public V this[K k]
{
get
{
if ( KeyComparer.Equ als(k, Key) )
return Value;
else
return Parent[k];
}
set {
if (KeyComparer.Eq uals(k, Key))
Value = value;
else
Parent[k] = value;
}
}
public ICollection<K> Keys { get { return new
AddItem<K>(Pare nt.Keys, Key, KeyComparer); } }
public ICollection<V> Values { get { return new
AddItem<V>(Pare nt.Values, Value, ValueComparer); } }
public void Clear() { throw Immutable.Make( this,
string.Format(" Cannot clear {0}", this)); }
public void Add(KeyValuePai r<K, V> kvp)
{
if (KeyComparer.Eq uals(kvp.Key, Key))
throw new ArgumentExcepti on(string.Forma t("{0} already
contains {1}", this, kvp.Key));
else
Parent.Add(kvp) ;
}
public bool Contains(KeyVal uePair<K, V> kvp)
{
V v;
return TryGetValue(kvp .Key, out v) &&
ValueComparer.E quals(kvp.Value , v);
}
public void CopyTo(KeyValue Pair<K, V>[] kvps, int index)
{
kvps[index++] = new KeyValuePair<K, V>(Key, Value);
Parent.CopyTo(k vps, index + 1);
}
public bool Remove(KeyValue Pair<K, V> kvp)
{
if (KeyComparer.Eq uals(kvp.Key, Key))
throw Immutable.Make( this, string.Format(" Cannot remove key:
{0}", kvp.Key));
else
return Parent.Remove(k vp);
}
public int Count { get { return Parent.Count + 1; } }
public bool IsReadOnly { get { return Parent.IsReadOn ly; } }
public IEnumerator<Key ValuePair<K, V>> GetEnumerator()
{
yield return new KeyValuePair<K, V>(Key, Value);
foreach (KeyValuePair<K , V> kvp in Parent)
yield return kvp;
}
System.Collecti ons.IEnumerator
System.Collecti ons.IEnumerable .GetEnumerator( ) { return GetEnumerator() ; }
}
#endregion
--
Helge Jensen
mailto:he****** ****@slog.dk
sip:he********* *@slog.dk
-=> Sebastian cover-music: http://ungdomshus.nu <=-
Mar 3 '06 #4
Adam Clauss <ca*****@tamu.e du> wrote:

<snip>
Does that "read-only" aspect buy me any alternatives?


Yes. You can write a generic wrapper class which implements
IDictionary<T> and delegates all the reading to an IDictionary<U> where
U : T (where this dictionary would be supplied at construction), and
throws an exception for all "writing" operations. You'll have to write
wrappers for iteration etc as well, unfortunately.

My guess is that someone else has already written such wrappers, but I
don't know of any unfortunately.

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Mar 4 '06 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

18
3051
by: Steven Bethard | last post by:
In the "empty classes as c structs?" thread, we've been talking in some detail about my proposed "generic objects" PEP. Based on a number of suggestions, I'm thinking more and more that instead of a single collections type, I should be proposing a new "namespaces" module instead. Some of my reasons: (1) Namespace is feeling less and less like a collection to me. Even though it's still intended as a data-only structure, the use cases...
2
2034
by: Jasper Kent | last post by:
I'm trying to do the equivalent of using typedefs with templates in C++ to avoid long instantiation names. I can do this okay: using BigDictionary = System.Collections.Generic.Dictionary<int, System.Collections.Generic.Dictionary<int, string>>; class MyClass {
22
13117
by: Adam Clauss | last post by:
OK, I have class A defined as follows: class A { A(Queue<B> queue) { ... } } Now, I then have a subclass of both classes A and B. The subclass of A (SubA), more specifically is passed a Queue<SubB>.
2
1531
by: Harold Howe | last post by:
Howdy all, I am getting a compiler error regarding a consrained conversion. It complains that it can't make the type conversion, even though the generic type argument inherits from the target of the conversion. I have trimmed my source down as much as possible. The classes implement something that behaves sort of like the Mediator design pattern, but where the colleagues are abstract, and can be added or removed on the fly. I guess...
25
3033
by: Lars | last post by:
Hi, I have a base class holding a generic list that needs to be accessed by both the base class and its subclasses. What is the best solution to this? I am fairly new to generics, but I am aware of that fact that if you have a class B, that inherits from A, then List<Bdoes NOT inherit from List<A>. So I understand why the example below does not compile, but I fail to
2
1490
by: Angel Mateos | last post by:
I have this structure: Class ElemBase Class Elem1 : Inherits ElemBase Class ColecBase(Of GenElem As {ElemBase, New}) : Inherits System.ComponentModel.BindingList(Of GenElem) Class Colec1 : Inherits ColecBase(Of Elem1)
4
7568
by: =?Utf-8?B?QkogU2FmZGll?= | last post by:
We have a class that has a public property that is of type List<T>. FXCop generates a DoNotExposeGenericLists error, indicating "System.Collections.Generic.List<Tis a generic collection designed for performance not inheritance and, therefore, does not contain any virtual members. The following generic collections are designed for inheritance and should be exposed instead of System.Collections.Generic.List<T>. *...
13
3837
by: rkausch | last post by:
Hello everyone, I'm writing because I'm frustrated with the implementation of C#'s generics, and need a workaround. I come from a Java background, and am currently writing a portion of an application that needs implementations in both Java and C#. I have the Java side done, and it works fantastic, and the C# side is nearly there. The problem I'm running into has to do with the differences in implementations of Generics between the two...
2
4183
by: SimonDotException | last post by:
I am trying to use reflection in a property of a base type to inspect the properties of an instance of a type which is derived from that base type, when the properties can themselves be instances of types derived from that base type, or arrays or generic collections of instances of types derived from that base type. All is well until I come to the properties which are generic collections, I don't seem to be able to find an elegant way of...
0
9521
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9333
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10107
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9945
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9765
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8768
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5214
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5361
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2733
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.